mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
Code cleanup.
This commit is contained in:
@@ -58,8 +58,10 @@ namespace DiscImageChef.Devices
|
||||
/// sense
|
||||
/// </param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendScsiCommand(object fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer,
|
||||
uint timeout, ScsiDirection direction, out double duration, out bool sense)
|
||||
internal static int SendScsiCommand(object fd, byte[] cdb, ref byte[] buffer,
|
||||
out byte[] senseBuffer,
|
||||
uint timeout, ScsiDirection direction, out double duration,
|
||||
out bool sense)
|
||||
{
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
|
||||
@@ -84,9 +86,10 @@ namespace DiscImageChef.Devices
|
||||
/// sense
|
||||
/// </param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendScsiCommand(PlatformID ptId, object fd, byte[] cdb, ref byte[] buffer,
|
||||
out byte[] senseBuffer, uint timeout, ScsiDirection direction,
|
||||
out double duration, out bool sense)
|
||||
internal static int SendScsiCommand(PlatformID ptId, object fd, byte[] cdb,
|
||||
ref byte[] buffer,
|
||||
out byte[] senseBuffer, uint timeout, ScsiDirection direction,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
switch(ptId)
|
||||
{
|
||||
@@ -181,14 +184,17 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferRegister">What register contains the transfer length</param>
|
||||
/// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendAtaCommand(object fd, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
||||
bool transferBlocks, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(object fd, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout,
|
||||
bool transferBlocks, out double duration,
|
||||
out bool sense)
|
||||
{
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
|
||||
return SendAtaCommand(ptId, fd, registers, out errorRegisters, protocol, transferRegister, ref buffer,
|
||||
return SendAtaCommand(ptId, fd, registers, out errorRegisters, protocol, transferRegister,
|
||||
ref buffer,
|
||||
timeout, transferBlocks, out duration, out sense);
|
||||
}
|
||||
|
||||
@@ -208,10 +214,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferRegister">What register contains the transfer length</param>
|
||||
/// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendAtaCommand(PlatformID ptId, object fd, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
||||
bool transferBlocks, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(PlatformID ptId, object fd,
|
||||
AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout,
|
||||
bool transferBlocks, out double duration,
|
||||
out bool sense)
|
||||
{
|
||||
switch(ptId)
|
||||
{
|
||||
@@ -223,6 +232,7 @@ namespace DiscImageChef.Devices
|
||||
Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0)
|
||||
return Windows.Command.SendIdeCommand((SafeFileHandle)fd, registers, out errorRegisters,
|
||||
protocol, ref buffer, timeout, out duration, out sense);
|
||||
|
||||
// Windows NT 4 or earlier, requires special ATA pass thru SCSI. But DiscImageChef cannot run there (or can it?)
|
||||
if(Environment.OSVersion.Version.Major <= 4)
|
||||
throw new InvalidOperationException("Windows NT 4.0 or earlier is not supported.");
|
||||
@@ -260,14 +270,17 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferRegister">What register contains the transfer length</param>
|
||||
/// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendAtaCommand(object fd, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
||||
bool transferBlocks, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(object fd, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout,
|
||||
bool transferBlocks, out double duration,
|
||||
out bool sense)
|
||||
{
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
|
||||
return SendAtaCommand(ptId, fd, registers, out errorRegisters, protocol, transferRegister, ref buffer,
|
||||
return SendAtaCommand(ptId, fd, registers, out errorRegisters, protocol, transferRegister,
|
||||
ref buffer,
|
||||
timeout, transferBlocks, out duration, out sense);
|
||||
}
|
||||
|
||||
@@ -287,10 +300,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferRegister">What register contains the transfer length</param>
|
||||
/// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendAtaCommand(PlatformID ptId, object fd, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
||||
bool transferBlocks, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(PlatformID ptId, object fd,
|
||||
AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout,
|
||||
bool transferBlocks, out double duration,
|
||||
out bool sense)
|
||||
{
|
||||
switch(ptId)
|
||||
{
|
||||
@@ -302,6 +318,7 @@ namespace DiscImageChef.Devices
|
||||
Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0)
|
||||
return Windows.Command.SendIdeCommand((SafeFileHandle)fd, registers, out errorRegisters,
|
||||
protocol, ref buffer, timeout, out duration, out sense);
|
||||
|
||||
// Windows NT 4 or earlier, requires special ATA pass thru SCSI. But DiscImageChef cannot run there (or can it?)
|
||||
if(Environment.OSVersion.Version.Major <= 4)
|
||||
throw new InvalidOperationException("Windows NT 4.0 or earlier is not supported.");
|
||||
@@ -339,14 +356,17 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferRegister">What register contains the transfer length</param>
|
||||
/// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendAtaCommand(object fd, AtaRegistersLba48 registers,
|
||||
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
||||
bool transferBlocks, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(object fd, AtaRegistersLba48 registers,
|
||||
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout,
|
||||
bool transferBlocks, out double duration,
|
||||
out bool sense)
|
||||
{
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
|
||||
return SendAtaCommand(ptId, fd, registers, out errorRegisters, protocol, transferRegister, ref buffer,
|
||||
return SendAtaCommand(ptId, fd, registers, out errorRegisters, protocol, transferRegister,
|
||||
ref buffer,
|
||||
timeout, transferBlocks, out duration, out sense);
|
||||
}
|
||||
|
||||
@@ -366,10 +386,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferRegister">What register contains the transfer length</param>
|
||||
/// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendAtaCommand(PlatformID ptId, object fd, AtaRegistersLba48 registers,
|
||||
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
||||
bool transferBlocks, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(PlatformID ptId, object fd,
|
||||
AtaRegistersLba48 registers,
|
||||
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
|
||||
AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout,
|
||||
bool transferBlocks, out double duration,
|
||||
out bool sense)
|
||||
{
|
||||
switch(ptId)
|
||||
{
|
||||
@@ -412,14 +435,18 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="response">Response registers</param>
|
||||
/// <param name="blockSize">Size of block in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendMmcCommand(object fd, MmcCommands command, bool write, bool isApplication,
|
||||
MmcFlags flags, uint argument, uint blockSize, uint blocks,
|
||||
ref byte[] buffer, out uint[] response, out double duration, out bool sense,
|
||||
uint timeout = 0)
|
||||
internal static int SendMmcCommand(object fd, MmcCommands command, bool write,
|
||||
bool isApplication,
|
||||
MmcFlags flags, uint argument, uint blockSize,
|
||||
uint blocks,
|
||||
ref byte[] buffer, out uint[] response, out double duration,
|
||||
out bool sense,
|
||||
uint timeout = 0)
|
||||
{
|
||||
PlatformID ptId = DetectOS.GetRealPlatformID();
|
||||
|
||||
return SendMmcCommand(ptId, (int)fd, command, write, isApplication, flags, argument, blockSize, blocks,
|
||||
return SendMmcCommand(ptId, (int)fd, command, write, isApplication, flags, argument,
|
||||
blockSize, blocks,
|
||||
ref buffer, out response, out duration, out sense, timeout);
|
||||
}
|
||||
|
||||
@@ -442,10 +469,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="response">Response registers</param>
|
||||
/// <param name="blockSize">Size of block in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
|
||||
internal static int SendMmcCommand(PlatformID ptId, object fd, MmcCommands command, bool write,
|
||||
bool isApplication, MmcFlags flags, uint argument, uint blockSize,
|
||||
uint blocks, ref byte[] buffer, out uint[] response, out double duration,
|
||||
out bool sense, uint timeout = 0)
|
||||
internal static int SendMmcCommand(PlatformID ptId, object fd, MmcCommands command,
|
||||
bool write,
|
||||
bool isApplication, MmcFlags flags, uint argument,
|
||||
uint blockSize,
|
||||
uint blocks, ref byte[] buffer, out uint[] response,
|
||||
out double duration,
|
||||
out bool sense, uint timeout = 0)
|
||||
{
|
||||
switch(ptId)
|
||||
{
|
||||
|
||||
@@ -43,8 +43,9 @@ namespace DiscImageChef.Devices
|
||||
buffer = new byte[512];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28 {Command = (byte)AtaCommands.ReadBuffer};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -59,8 +60,8 @@ namespace DiscImageChef.Devices
|
||||
buffer = new byte[512];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28 {Command = (byte)AtaCommands.ReadBufferDma};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.NoTransfer,
|
||||
ref buffer, timeout, false, out duration, out bool sense);
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.NoTransfer,
|
||||
ref buffer, timeout, false, out duration, out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("ATA Device", "READ BUFFER DMA took {0} ms.", duration);
|
||||
@@ -68,29 +69,30 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba, byte count,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba, byte count,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return ReadDma(out buffer, out statusRegisters, true, lba, count, timeout, out duration);
|
||||
}
|
||||
|
||||
public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, bool retry, uint lba,
|
||||
byte count, uint timeout, out double duration)
|
||||
public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, bool retry, uint lba,
|
||||
byte count, uint timeout, out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
{
|
||||
SectorCount = count,
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1),
|
||||
Command = retry ? (byte)AtaCommands.ReadDmaRetry : (byte)AtaCommands.ReadDma
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1),
|
||||
Command = retry ? (byte)AtaCommands.ReadDmaRetry : (byte)AtaCommands.ReadDma
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma,
|
||||
AtaTransferRegister.SectorCount,
|
||||
ref buffer, timeout, true, out duration, out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -99,24 +101,25 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba, byte count,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba, byte count,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
{
|
||||
Command = (byte)AtaCommands.ReadMultiple,
|
||||
Command = (byte)AtaCommands.ReadMultiple,
|
||||
SectorCount = count,
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1)
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1)
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -125,17 +128,18 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadNativeMaxAddress(out uint lba, out AtaErrorRegistersLba28 statusRegisters, uint timeout,
|
||||
public bool ReadNativeMaxAddress(out uint lba, out AtaErrorRegistersLba28 statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
lba = 0;
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28 {Command = (byte)AtaCommands.ReadNativeMaxAddress};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -144,7 +148,7 @@ namespace DiscImageChef.Devices
|
||||
lba += (uint)(statusRegisters.DeviceHead & 0xF);
|
||||
lba *= 0x1000000;
|
||||
lba += (uint)(statusRegisters.LbaHigh << 16);
|
||||
lba += (uint)(statusRegisters.LbaMid << 8);
|
||||
lba += (uint)(statusRegisters.LbaMid << 8);
|
||||
lba += statusRegisters.LbaLow;
|
||||
}
|
||||
|
||||
@@ -153,30 +157,31 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool Read(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba, byte count,
|
||||
uint timeout, out double duration)
|
||||
public bool Read(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba, byte count,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return Read(out buffer, out statusRegisters, true, lba, count, timeout, out duration);
|
||||
}
|
||||
|
||||
public bool Read(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, bool retry, uint lba,
|
||||
byte count, uint timeout, out double duration)
|
||||
public bool Read(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, bool retry, uint lba,
|
||||
byte count, uint timeout, out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
{
|
||||
SectorCount = count,
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1),
|
||||
Command = retry ? (byte)AtaCommands.ReadRetry : (byte)AtaCommands.Read
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1),
|
||||
Command = retry ? (byte)AtaCommands.ReadRetry : (byte)AtaCommands.Read
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -185,30 +190,32 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadLong(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadLong(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return ReadLong(out buffer, out statusRegisters, true, lba, blockSize, timeout, out duration);
|
||||
}
|
||||
|
||||
public bool ReadLong(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, bool retry, uint lba,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
public bool ReadLong(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, bool retry,
|
||||
uint lba,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[blockSize];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
{
|
||||
SectorCount = 1,
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1),
|
||||
Command = retry ? (byte)AtaCommands.ReadLongRetry : (byte)AtaCommands.ReadLong
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1),
|
||||
Command = retry ? (byte)AtaCommands.ReadLongRetry : (byte)AtaCommands.ReadLong
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -222,17 +229,18 @@ namespace DiscImageChef.Devices
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
{
|
||||
Command = (byte)AtaCommands.Seek,
|
||||
Command = (byte)AtaCommands.Seek,
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1)
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1)
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
public partial class Device
|
||||
{
|
||||
public bool GetNativeMaxAddressExt(out ulong lba, out AtaErrorRegistersLba48 statusRegisters, uint timeout,
|
||||
public bool GetNativeMaxAddressExt(out ulong lba, out AtaErrorRegistersLba48 statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
lba = 0;
|
||||
@@ -45,14 +45,15 @@ namespace DiscImageChef.Devices
|
||||
AtaRegistersLba48 registers =
|
||||
new AtaRegistersLba48 {Command = (byte)AtaCommands.NativeMaxAddress, Feature = 0x0000};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
if((statusRegisters.Status & 0x23) == 0)
|
||||
{
|
||||
lba = statusRegisters.LbaHigh;
|
||||
lba = statusRegisters.LbaHigh;
|
||||
lba *= 0x100000000;
|
||||
lba += (ulong)(statusRegisters.LbaMid << 16);
|
||||
lba += statusRegisters.LbaLow;
|
||||
@@ -63,22 +64,23 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, ulong lba, ushort count,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, ulong lba, ushort count,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 65536] : new byte[512 * count];
|
||||
AtaRegistersLba48 registers = new AtaRegistersLba48
|
||||
{
|
||||
Command = (byte)AtaCommands.ReadDmaExt,
|
||||
Command = (byte)AtaCommands.ReadDmaExt,
|
||||
SectorCount = count,
|
||||
LbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000),
|
||||
LbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000),
|
||||
LbaLow = (ushort)((lba & 0xFFFF) / 0x1)
|
||||
LbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000),
|
||||
LbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000),
|
||||
LbaLow = (ushort)((lba & 0xFFFF) / 0x1)
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma,
|
||||
AtaTransferRegister.SectorCount,
|
||||
ref buffer, timeout, true, out duration, out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -87,22 +89,24 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadLog(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, byte logAddress,
|
||||
ushort pageNumber, ushort count, uint timeout, out double duration)
|
||||
public bool ReadLog(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, byte logAddress,
|
||||
ushort pageNumber, ushort count, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = new byte[512 * count];
|
||||
AtaRegistersLba48 registers = new AtaRegistersLba48
|
||||
{
|
||||
Command = (byte)AtaCommands.ReadLogExt,
|
||||
Command = (byte)AtaCommands.ReadLogExt,
|
||||
SectorCount = count,
|
||||
LbaLow = (ushort)((pageNumber & 0xFF) * 0x100),
|
||||
LbaHigh = (ushort)((pageNumber & 0xFF00) / 0x100)
|
||||
LbaLow = (ushort)((pageNumber & 0xFF) * 0x100),
|
||||
LbaHigh = (ushort)((pageNumber & 0xFF00) / 0x100)
|
||||
};
|
||||
|
||||
registers.LbaLow += logAddress;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -111,21 +115,23 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadLogDma(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, byte logAddress,
|
||||
ushort pageNumber, ushort count, uint timeout, out double duration)
|
||||
public bool ReadLogDma(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, byte logAddress,
|
||||
ushort pageNumber, ushort count, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = new byte[512 * count];
|
||||
AtaRegistersLba48 registers = new AtaRegistersLba48
|
||||
{
|
||||
Command = (byte)AtaCommands.ReadLogDmaExt,
|
||||
Command = (byte)AtaCommands.ReadLogDmaExt,
|
||||
SectorCount = count,
|
||||
LbaLow = (ushort)((pageNumber & 0xFF) * 0x100),
|
||||
LbaHigh = (ushort)((pageNumber & 0xFF00) / 0x100)
|
||||
LbaLow = (ushort)((pageNumber & 0xFF) * 0x100),
|
||||
LbaHigh = (ushort)((pageNumber & 0xFF00) / 0x100)
|
||||
};
|
||||
|
||||
registers.LbaLow += logAddress;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma,
|
||||
AtaTransferRegister.SectorCount,
|
||||
ref buffer, timeout, true, out duration, out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -134,23 +140,25 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, ulong lba, ushort count,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, ulong lba,
|
||||
ushort count,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 65536] : new byte[512 * count];
|
||||
AtaRegistersLba48 registers = new AtaRegistersLba48
|
||||
{
|
||||
Command = (byte)AtaCommands.ReadMultipleExt,
|
||||
Command = (byte)AtaCommands.ReadMultipleExt,
|
||||
SectorCount = count,
|
||||
LbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000),
|
||||
LbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000),
|
||||
LbaLow = (ushort)((lba & 0xFFFF) / 0x1)
|
||||
LbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000),
|
||||
LbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000),
|
||||
LbaLow = (ushort)((lba & 0xFFFF) / 0x1)
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -159,23 +167,24 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadNativeMaxAddress(out ulong lba, out AtaErrorRegistersLba48 statusRegisters, uint timeout,
|
||||
public bool ReadNativeMaxAddress(out ulong lba, out AtaErrorRegistersLba48 statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
lba = 0;
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersLba48 registers = new AtaRegistersLba48 {Command = (byte)AtaCommands.ReadNativeMaxAddressExt};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
if((statusRegisters.Status & 0x23) == 0)
|
||||
{
|
||||
lba = statusRegisters.LbaHigh;
|
||||
lba = statusRegisters.LbaHigh;
|
||||
lba *= 0x100000000;
|
||||
lba += (ulong)(statusRegisters.LbaMid << 16);
|
||||
lba += statusRegisters.LbaLow;
|
||||
@@ -186,23 +195,24 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool Read(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, ulong lba, ushort count,
|
||||
uint timeout, out double duration)
|
||||
public bool Read(out byte[] buffer, out AtaErrorRegistersLba48 statusRegisters, ulong lba, ushort count,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 65536] : new byte[512 * count];
|
||||
AtaRegistersLba48 registers = new AtaRegistersLba48
|
||||
{
|
||||
Command = (byte)AtaCommands.ReadExt,
|
||||
Command = (byte)AtaCommands.ReadExt,
|
||||
SectorCount = count,
|
||||
LbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000),
|
||||
LbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000),
|
||||
LbaLow = (ushort)((lba & 0xFFFF) / 0x1)
|
||||
LbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000),
|
||||
LbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000),
|
||||
LbaLow = (ushort)((lba & 0xFFFF) / 0x1)
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.SectorCount, ref buffer, timeout, true,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace DiscImageChef.Devices
|
||||
public bool AtaIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = new byte[512];
|
||||
buffer = new byte[512];
|
||||
AtaRegistersChs registers = new AtaRegistersChs {Command = (byte)AtaCommands.IdentifyDevice};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
@@ -106,16 +106,16 @@ namespace DiscImageChef.Devices
|
||||
}
|
||||
|
||||
public bool ReadDma(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder,
|
||||
byte head, byte sector, byte count, uint timeout,
|
||||
byte head, byte sector, byte count, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
AtaRegistersChs registers = new AtaRegistersChs
|
||||
{
|
||||
SectorCount = count,
|
||||
CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100),
|
||||
CylinderLow = (byte)((cylinder & 0xFF) / 0x1),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
Sector = sector,
|
||||
Command = retry ? (byte)AtaCommands.ReadDmaRetry : (byte)AtaCommands.ReadDma
|
||||
};
|
||||
@@ -130,18 +130,18 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder,
|
||||
byte head, byte sector, byte count,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder,
|
||||
byte head, byte sector, byte count,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
AtaRegistersChs registers = new AtaRegistersChs
|
||||
{
|
||||
Command = (byte)AtaCommands.ReadMultiple,
|
||||
SectorCount = count,
|
||||
CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100),
|
||||
CylinderLow = (byte)((cylinder & 0xFF) / 0x1),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
Sector = sector
|
||||
};
|
||||
|
||||
@@ -157,24 +157,24 @@ namespace DiscImageChef.Devices
|
||||
}
|
||||
|
||||
public bool Read(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head,
|
||||
byte sector, byte count, uint timeout,
|
||||
byte sector, byte count, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
return Read(out buffer, out statusRegisters, true, cylinder, head, sector, count, timeout, out duration);
|
||||
}
|
||||
|
||||
public bool Read(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder,
|
||||
byte head, byte sector, byte count, uint timeout,
|
||||
byte head, byte sector, byte count, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count];
|
||||
AtaRegistersChs registers = new AtaRegistersChs
|
||||
{
|
||||
Command = retry ? (byte)AtaCommands.ReadRetry : (byte)AtaCommands.Read,
|
||||
SectorCount = count,
|
||||
CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100),
|
||||
CylinderLow = (byte)((cylinder & 0xFF) / 0x1),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
Sector = sector
|
||||
};
|
||||
|
||||
@@ -198,18 +198,19 @@ namespace DiscImageChef.Devices
|
||||
out duration);
|
||||
}
|
||||
|
||||
public bool ReadLong(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder,
|
||||
byte head, byte sector, uint blockSize, uint timeout,
|
||||
out double duration)
|
||||
public bool ReadLong(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry,
|
||||
ushort cylinder,
|
||||
byte head, byte sector, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[blockSize];
|
||||
buffer = new byte[blockSize];
|
||||
AtaRegistersChs registers = new AtaRegistersChs
|
||||
{
|
||||
Command = retry ? (byte)AtaCommands.ReadLongRetry : (byte)AtaCommands.ReadLong,
|
||||
SectorCount = 1,
|
||||
CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100),
|
||||
CylinderLow = (byte)((cylinder & 0xFF) / 0x1),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
Sector = sector
|
||||
};
|
||||
|
||||
@@ -224,16 +225,16 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool Seek(out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, byte sector,
|
||||
uint timeout, out double duration)
|
||||
public bool Seek(out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, byte sector,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersChs registers = new AtaRegistersChs
|
||||
{
|
||||
Command = (byte)AtaCommands.Seek,
|
||||
CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100),
|
||||
CylinderLow = (byte)((cylinder & 0xFF) / 0x1),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
Sector = sector
|
||||
};
|
||||
|
||||
@@ -254,16 +255,16 @@ namespace DiscImageChef.Devices
|
||||
}
|
||||
|
||||
public bool SetFeatures(out AtaErrorRegistersChs statusRegisters, AtaFeatures feature, ushort cylinder,
|
||||
byte head, byte sector, byte sectorCount,
|
||||
uint timeout, out double duration)
|
||||
byte head, byte sector, byte sectorCount,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersChs registers = new AtaRegistersChs
|
||||
{
|
||||
Command = (byte)AtaCommands.SetFeatures,
|
||||
CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100),
|
||||
CylinderLow = (byte)((cylinder & 0xFF) / 0x1),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
DeviceHead = (byte)(head & 0x0F),
|
||||
Sector = sector,
|
||||
SectorCount = sectorCount,
|
||||
Feature = (byte)feature
|
||||
|
||||
@@ -86,8 +86,9 @@ namespace DiscImageChef.Devices
|
||||
buffer = new byte[512];
|
||||
AtaRegistersChs registers = new AtaRegistersChs {Command = (byte)AtaCommands.IdentifyPacketDevice};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
|
||||
@@ -37,23 +37,24 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
public partial class Device
|
||||
{
|
||||
public bool TranslateSector(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba,
|
||||
uint timeout, out double duration)
|
||||
public bool TranslateSector(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, uint lba,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[512];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
{
|
||||
Command = (byte)AtaCommands.TranslateSector,
|
||||
Command = (byte)AtaCommands.TranslateSector,
|
||||
DeviceHead = (byte)((lba & 0xF000000) / 0x1000000),
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1)
|
||||
LbaHigh = (byte)((lba & 0xFF0000) / 0x10000),
|
||||
LbaMid = (byte)((lba & 0xFF00) / 0x100),
|
||||
LbaLow = (byte)((lba & 0xFF) / 0x1)
|
||||
};
|
||||
|
||||
registers.DeviceHead += 0x40;
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -63,20 +64,22 @@ namespace DiscImageChef.Devices
|
||||
}
|
||||
|
||||
public bool TranslateSector(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder,
|
||||
byte head, byte sector, uint timeout, out double duration)
|
||||
byte head, byte sector, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = new byte[512];
|
||||
AtaRegistersChs registers = new AtaRegistersChs
|
||||
{
|
||||
Command = (byte)AtaCommands.TranslateSector,
|
||||
Command = (byte)AtaCommands.TranslateSector,
|
||||
CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100),
|
||||
CylinderLow = (byte)((cylinder & 0xFF) / 0x1),
|
||||
Sector = sector,
|
||||
DeviceHead = (byte)(head & 0x0F)
|
||||
CylinderLow = (byte)((cylinder & 0xFF) / 0x1),
|
||||
Sector = sector,
|
||||
DeviceHead = (byte)(head & 0x0F)
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -86,13 +89,14 @@ namespace DiscImageChef.Devices
|
||||
}
|
||||
|
||||
public bool RequestExtendedErrorCode(out byte errorCode, out AtaErrorRegistersLba28 statusRegisters,
|
||||
uint timeout, out double duration)
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28 {Command = (byte)AtaCommands.RequestSense};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
|
||||
@@ -38,26 +38,27 @@ namespace DiscImageChef.Devices
|
||||
public partial class Device
|
||||
{
|
||||
public bool EnableMediaCardPassThrough(out AtaErrorRegistersChs statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
out double duration)
|
||||
{
|
||||
return CheckMediaCardType(1, out statusRegisters, timeout, out duration);
|
||||
}
|
||||
|
||||
public bool DisableMediaCardPassThrough(out AtaErrorRegistersChs statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
out double duration)
|
||||
{
|
||||
return CheckMediaCardType(0, out statusRegisters, timeout, out duration);
|
||||
}
|
||||
|
||||
public bool CheckMediaCardType(byte feature, out AtaErrorRegistersChs statusRegisters, uint timeout,
|
||||
public bool CheckMediaCardType(byte feature, out AtaErrorRegistersChs statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersChs registers =
|
||||
new AtaRegistersChs {Command = (byte)AtaCommands.CheckMediaCardType, Feature = feature};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
|
||||
@@ -45,11 +45,12 @@ namespace DiscImageChef.Devices
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.Disable,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F
|
||||
LbaMid = 0x4F
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -59,20 +60,21 @@ namespace DiscImageChef.Devices
|
||||
}
|
||||
|
||||
public bool SmartEnableAttributeAutosave(out AtaErrorRegistersLba28 statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
{
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.EnableDisableAttributeAutosave,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F,
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.EnableDisableAttributeAutosave,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F,
|
||||
SectorCount = 0xF1
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -82,7 +84,7 @@ namespace DiscImageChef.Devices
|
||||
}
|
||||
|
||||
public bool SmartDisableAttributeAutosave(out AtaErrorRegistersLba28 statusRegisters, uint timeout,
|
||||
out double duration)
|
||||
out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
@@ -90,11 +92,12 @@ namespace DiscImageChef.Devices
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.EnableDisableAttributeAutosave,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F
|
||||
LbaMid = 0x4F
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -111,11 +114,12 @@ namespace DiscImageChef.Devices
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.Enable,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F
|
||||
LbaMid = 0x4F
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -124,8 +128,8 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool SmartExecuteOffLineImmediate(out AtaErrorRegistersLba28 statusRegisters, byte subcommand,
|
||||
uint timeout, out double duration)
|
||||
public bool SmartExecuteOffLineImmediate(out AtaErrorRegistersLba28 statusRegisters, byte subcommand,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
@@ -133,12 +137,13 @@ namespace DiscImageChef.Devices
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.ExecuteOfflineImmediate,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F,
|
||||
LbaLow = subcommand
|
||||
LbaMid = 0x4F,
|
||||
LbaLow = subcommand
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -156,11 +161,12 @@ namespace DiscImageChef.Devices
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.ReadData,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F
|
||||
LbaMid = 0x4F
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -169,8 +175,8 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool SmartReadLog(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, byte logAddress,
|
||||
uint timeout, out double duration)
|
||||
public bool SmartReadLog(out byte[] buffer, out AtaErrorRegistersLba28 statusRegisters, byte logAddress,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[512];
|
||||
AtaRegistersLba28 registers = new AtaRegistersLba28
|
||||
@@ -178,12 +184,13 @@ namespace DiscImageChef.Devices
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.ReadLog,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F,
|
||||
LbaLow = logAddress
|
||||
LbaMid = 0x4F,
|
||||
LbaLow = logAddress
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
@@ -200,11 +207,12 @@ namespace DiscImageChef.Devices
|
||||
Command = (byte)AtaCommands.Smart,
|
||||
Feature = (byte)AtaSmartSubCommands.ReturnStatus,
|
||||
LbaHigh = 0xC2,
|
||||
LbaMid = 0x4F
|
||||
LbaMid = 0x4F
|
||||
};
|
||||
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
|
||||
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData,
|
||||
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
|
||||
out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ namespace DiscImageChef.Devices
|
||||
/// <c>True</c> if SCSI command returned non-OK status and <paramref name="senseBuffer" /> contains
|
||||
/// SCSI sense
|
||||
/// </param>
|
||||
public int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
|
||||
ScsiDirection direction, out double duration, out bool sense)
|
||||
public int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
|
||||
ScsiDirection direction, out double duration, out bool sense)
|
||||
{
|
||||
return Command.SendScsiCommand(PlatformId, FileHandle, cdb, ref buffer, out senseBuffer, timeout, direction,
|
||||
out duration, out sense);
|
||||
@@ -77,8 +77,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Time it took to execute the command in milliseconds</param>
|
||||
/// <param name="sense"><c>True</c> if ATA/ATAPI command returned non-OK status</param>
|
||||
public int SendAtaCommand(AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters,
|
||||
AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout, bool transferBlocks, out double duration, out bool sense)
|
||||
AtaProtocol protocol, AtaTransferRegister transferRegister,
|
||||
ref byte[] buffer,
|
||||
uint timeout, bool transferBlocks,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
return Command.SendAtaCommand(PlatformId, FileHandle, registers, out errorRegisters, protocol,
|
||||
transferRegister, ref buffer, timeout, transferBlocks, out duration,
|
||||
@@ -102,8 +104,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Time it took to execute the command in milliseconds</param>
|
||||
/// <param name="sense"><c>True</c> if ATA/ATAPI command returned non-OK status</param>
|
||||
public int SendAtaCommand(AtaRegistersLba28 registers, out AtaErrorRegistersLba28 errorRegisters,
|
||||
AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout, bool transferBlocks, out double duration, out bool sense)
|
||||
AtaProtocol protocol, AtaTransferRegister transferRegister,
|
||||
ref byte[] buffer,
|
||||
uint timeout, bool transferBlocks,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
return Command.SendAtaCommand(PlatformId, FileHandle, registers, out errorRegisters, protocol,
|
||||
transferRegister, ref buffer, timeout, transferBlocks, out duration,
|
||||
@@ -127,8 +131,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Time it took to execute the command in milliseconds</param>
|
||||
/// <param name="sense"><c>True</c> if ATA/ATAPI command returned non-OK status</param>
|
||||
public int SendAtaCommand(AtaRegistersLba48 registers, out AtaErrorRegistersLba48 errorRegisters,
|
||||
AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
|
||||
uint timeout, bool transferBlocks, out double duration, out bool sense)
|
||||
AtaProtocol protocol, AtaTransferRegister transferRegister,
|
||||
ref byte[] buffer,
|
||||
uint timeout, bool transferBlocks,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
return Command.SendAtaCommand(PlatformId, FileHandle, registers, out errorRegisters, protocol,
|
||||
transferRegister, ref buffer, timeout, transferBlocks, out duration,
|
||||
@@ -151,9 +157,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="argument">Command argument</param>
|
||||
/// <param name="response">Response registers</param>
|
||||
/// <param name="blockSize">Size of block in bytes</param>
|
||||
public int SendMmcCommand(MmcCommands command, bool write, bool isApplication, MmcFlags flags, uint argument,
|
||||
uint blockSize, uint blocks, ref byte[] buffer, out uint[] response,
|
||||
out double duration, out bool sense, uint timeout = 0)
|
||||
public int SendMmcCommand(MmcCommands command, bool write, bool isApplication, MmcFlags flags,
|
||||
uint argument,
|
||||
uint blockSize, uint blocks, ref byte[] buffer, out uint[] response,
|
||||
out double duration, out bool sense, uint timeout = 0)
|
||||
{
|
||||
switch(command)
|
||||
{
|
||||
@@ -163,7 +170,7 @@ namespace DiscImageChef.Devices
|
||||
buffer = new byte[cachedCid.Length];
|
||||
Array.Copy(cachedCid, buffer, buffer.Length);
|
||||
response = new uint[4];
|
||||
sense = false;
|
||||
sense = false;
|
||||
DateTime end = DateTime.Now;
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
return 0;
|
||||
@@ -174,7 +181,7 @@ namespace DiscImageChef.Devices
|
||||
buffer = new byte[cachedCsd.Length];
|
||||
Array.Copy(cachedCsd, buffer, buffer.Length);
|
||||
response = new uint[4];
|
||||
sense = false;
|
||||
sense = false;
|
||||
DateTime end = DateTime.Now;
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
return 0;
|
||||
@@ -185,7 +192,7 @@ namespace DiscImageChef.Devices
|
||||
buffer = new byte[cachedScr.Length];
|
||||
Array.Copy(cachedScr, buffer, buffer.Length);
|
||||
response = new uint[4];
|
||||
sense = false;
|
||||
sense = false;
|
||||
DateTime end = DateTime.Now;
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
return 0;
|
||||
@@ -203,7 +210,7 @@ namespace DiscImageChef.Devices
|
||||
buffer = new byte[cachedOcr.Length];
|
||||
Array.Copy(cachedOcr, buffer, buffer.Length);
|
||||
response = new uint[4];
|
||||
sense = false;
|
||||
sense = false;
|
||||
DateTime end = DateTime.Now;
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
return 0;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace DiscImageChef.Devices
|
||||
public string Model;
|
||||
public string Serial;
|
||||
public string Bus;
|
||||
public bool Supported;
|
||||
public bool Supported;
|
||||
}
|
||||
|
||||
public partial class Device
|
||||
@@ -53,7 +53,7 @@ namespace DiscImageChef.Devices
|
||||
switch(DetectOS.GetRealPlatformID())
|
||||
{
|
||||
case PlatformID.Win32NT: return Windows.ListDevices.GetList();
|
||||
case PlatformID.Linux: return Linux.ListDevices.GetList();
|
||||
case PlatformID.Linux: return Linux.ListDevices.GetList();
|
||||
case PlatformID.FreeBSD: return FreeBSD.ListDevices.GetList();
|
||||
default:
|
||||
throw new InvalidOperationException($"Platform {DetectOS.GetRealPlatformID()} not yet supported.");
|
||||
|
||||
@@ -40,9 +40,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
buffer = new byte[16];
|
||||
|
||||
LastError = SendMmcCommand(MmcCommands.SendCsd, false, false,
|
||||
MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 | MmcFlags.CommandAc, 0, 16, 1,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand(MmcCommands.SendCsd, false,
|
||||
false,
|
||||
MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 | MmcFlags.CommandAc, 0,
|
||||
16, 1,
|
||||
ref buffer, out response,
|
||||
out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("MMC Device", "SEND_CSD took {0} ms.", duration);
|
||||
@@ -54,9 +57,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
buffer = new byte[16];
|
||||
|
||||
LastError = SendMmcCommand(MmcCommands.SendCid, false, false,
|
||||
MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 | MmcFlags.CommandAc, 0, 16, 1,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand(MmcCommands.SendCid, false,
|
||||
false,
|
||||
MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 | MmcFlags.CommandAc, 0,
|
||||
16, 1,
|
||||
ref buffer, out response,
|
||||
out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("MMC Device", "SEND_CID took {0} ms.", duration);
|
||||
@@ -68,9 +74,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
buffer = new byte[4];
|
||||
|
||||
LastError = SendMmcCommand(MmcCommands.SendOpCond, false, true,
|
||||
MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 | MmcFlags.CommandBcr, 0, 4, 1,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand(MmcCommands.SendOpCond, false,
|
||||
true,
|
||||
MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 | MmcFlags.CommandBcr, 0,
|
||||
4, 1,
|
||||
ref buffer, out response,
|
||||
out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("SecureDigital Device", "SEND_OP_COND took {0} ms.", duration);
|
||||
@@ -82,9 +91,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
buffer = new byte[512];
|
||||
|
||||
LastError = SendMmcCommand(MmcCommands.SendExtCsd, false, false,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc, 0, 512, 1,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand(MmcCommands.SendExtCsd, false,
|
||||
false,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc, 0,
|
||||
512, 1,
|
||||
ref buffer,
|
||||
out response, out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("MMC Device", "SEND_EXT_CSD took {0} ms.", duration);
|
||||
@@ -96,9 +108,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
LastError = SendMmcCommand(MmcCommands.SetBlocklen, false, false,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAc, length, 0, 0,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand(MmcCommands.SetBlocklen, false,
|
||||
false,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAc, length,
|
||||
0, 0,
|
||||
ref buffer, out response,
|
||||
out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("MMC Device", "SET_BLOCKLEN took {0} ms.", duration);
|
||||
@@ -106,28 +121,34 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool Read(out byte[] buffer, out uint[] response, uint lba, uint blockSize, uint transferLength,
|
||||
bool byteAddressed, uint timeout, out double duration)
|
||||
public bool Read(out byte[] buffer, out uint[] response, uint lba, uint blockSize,
|
||||
uint transferLength,
|
||||
bool byteAddressed, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[transferLength * blockSize];
|
||||
uint address;
|
||||
if(byteAddressed) address = lba * blockSize;
|
||||
else address = lba;
|
||||
else address = lba;
|
||||
|
||||
MmcCommands command = transferLength > 1 ? MmcCommands.ReadMultipleBlock : MmcCommands.ReadSingleBlock;
|
||||
|
||||
LastError = SendMmcCommand(command, false, false,
|
||||
LastError = SendMmcCommand(command, false,
|
||||
false,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc, address,
|
||||
blockSize, transferLength, ref buffer, out response, out duration,
|
||||
blockSize,
|
||||
transferLength, ref buffer, out response, out duration,
|
||||
out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
if(transferLength > 1)
|
||||
{
|
||||
byte[] foo = new byte[0];
|
||||
SendMmcCommand(MmcCommands.StopTransmission, false, false,
|
||||
MmcFlags.ResponseR1B | MmcFlags.ResponseSpiR1B | MmcFlags.CommandAc, 0, 0, 0, ref foo,
|
||||
out _, out double stopDuration, out bool _, timeout);
|
||||
SendMmcCommand(MmcCommands.StopTransmission, false,
|
||||
false,
|
||||
MmcFlags.ResponseR1B | MmcFlags.ResponseSpiR1B | MmcFlags.CommandAc, 0,
|
||||
0, 0, ref foo,
|
||||
out _,
|
||||
out double stopDuration, out bool _, timeout);
|
||||
duration += stopDuration;
|
||||
DicConsole.DebugWriteLine("MMC Device", "READ_MULTIPLE_BLOCK took {0} ms.", duration);
|
||||
}
|
||||
@@ -140,9 +161,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
buffer = new byte[4];
|
||||
|
||||
LastError = SendMmcCommand(MmcCommands.SendStatus, false, true,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAc, 0, 4, 1,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand(MmcCommands.SendStatus, false,
|
||||
true,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAc, 0,
|
||||
4, 1,
|
||||
ref buffer, out response,
|
||||
out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("SecureDigital Device", "SEND_STATUS took {0} ms.", duration);
|
||||
|
||||
@@ -40,9 +40,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
buffer = new byte[64];
|
||||
|
||||
LastError = SendMmcCommand((MmcCommands)SecureDigitalCommands.SendStatus, false, true,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc, 0, 64, 1,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand((MmcCommands)SecureDigitalCommands.SendStatus, false,
|
||||
true,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc, 0,
|
||||
64, 1,
|
||||
ref buffer,
|
||||
out response, out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("SecureDigital Device", "SD_STATUS took {0} ms.", duration);
|
||||
@@ -54,9 +57,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
buffer = new byte[4];
|
||||
|
||||
LastError = SendMmcCommand((MmcCommands)SecureDigitalCommands.SendOperatingCondition, false, true,
|
||||
MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 | MmcFlags.CommandBcr, 0, 4, 1,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand((MmcCommands)SecureDigitalCommands.SendOperatingCondition, false,
|
||||
true,
|
||||
MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 | MmcFlags.CommandBcr, 0,
|
||||
4, 1,
|
||||
ref buffer, out response,
|
||||
out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("SecureDigital Device", "SD_SEND_OP_COND took {0} ms.", duration);
|
||||
@@ -68,9 +74,12 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
buffer = new byte[8];
|
||||
|
||||
LastError = SendMmcCommand((MmcCommands)SecureDigitalCommands.SendScr, false, true,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc, 0, 8, 1,
|
||||
ref buffer, out response, out duration, out bool sense, timeout);
|
||||
LastError = SendMmcCommand((MmcCommands)SecureDigitalCommands.SendScr, false,
|
||||
true,
|
||||
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc, 0,
|
||||
8, 1,
|
||||
ref buffer,
|
||||
out response, out duration, out bool sense, timeout);
|
||||
Error = LastError != 0;
|
||||
|
||||
DicConsole.DebugWriteLine("SecureDigital Device", "SEND_SCR took {0} ms.", duration);
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.AdaptecTranslate;
|
||||
cdb[1] = (byte)((lba & 0x1F0000) >> 16);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(lba & 0xFF);
|
||||
if(drive1) cdb[1] += 0x20;
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="drive1">If set to <c>true</c> set the threshold from drive 1.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool AdaptecSetErrorThreshold(byte threshold, out byte[] senseBuffer, bool drive1, uint timeout,
|
||||
public bool AdaptecSetErrorThreshold(byte threshold, out byte[] senseBuffer, bool drive1, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ArchiveRequestBlockAddress;
|
||||
cdb[1] = (byte)((lba & 0x1F0000) >> 16);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(lba & 0xFF);
|
||||
cdb[4] = 3;
|
||||
|
||||
@@ -90,12 +90,12 @@ namespace DiscImageChef.Devices
|
||||
out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ArchiveSeekBlock;
|
||||
cdb[1] = (byte)((lba & 0x1F0000) >> 16);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(lba & 0xFF);
|
||||
if(immediate) cdb[1] += 0x01;
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace DiscImageChef.Devices
|
||||
public bool CertanceParkUnpark(out byte[] senseBuffer, bool park, uint timeout, out double duration)
|
||||
{
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.CertanceParkUnpark;
|
||||
|
||||
@@ -38,22 +38,23 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
public partial class Device
|
||||
{
|
||||
public bool FujitsuDisplay(out byte[] senseBuffer, bool flash, FujitsuDisplayModes mode, string firstHalf,
|
||||
string secondHalf, uint timeout, out double duration)
|
||||
public bool FujitsuDisplay(out byte[] senseBuffer, bool flash, FujitsuDisplayModes mode, string firstHalf,
|
||||
string secondHalf, uint timeout, out double duration)
|
||||
{
|
||||
byte[] tmp;
|
||||
byte[] firstHalfBytes = new byte[8];
|
||||
byte[] firstHalfBytes = new byte[8];
|
||||
byte[] secondHalfBytes = new byte[8];
|
||||
byte[] buffer = new byte[17];
|
||||
bool displayLen = false;
|
||||
bool halfMsg = false;
|
||||
byte[] cdb = new byte[10];
|
||||
byte[] buffer = new byte[17];
|
||||
bool displayLen = false;
|
||||
bool halfMsg = false;
|
||||
byte[] cdb = new byte[10];
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(firstHalf))
|
||||
{
|
||||
tmp = Encoding.ASCII.GetBytes(firstHalf);
|
||||
Array.Copy(tmp, 0, firstHalfBytes, 0, 8);
|
||||
}
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(secondHalf))
|
||||
{
|
||||
tmp = Encoding.ASCII.GetBytes(secondHalf);
|
||||
@@ -62,17 +63,18 @@ namespace DiscImageChef.Devices
|
||||
|
||||
if(mode != FujitsuDisplayModes.Half)
|
||||
if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(firstHalfBytes) &&
|
||||
!ArrayHelpers.ArrayIsNullOrWhiteSpace(secondHalfBytes)) displayLen = true;
|
||||
!ArrayHelpers.ArrayIsNullOrWhiteSpace(secondHalfBytes))
|
||||
displayLen = true;
|
||||
else if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(firstHalfBytes) &&
|
||||
ArrayHelpers.ArrayIsNullOrWhiteSpace(secondHalfBytes)) halfMsg = true;
|
||||
|
||||
buffer[0] = (byte)((byte)mode << 5);
|
||||
if(displayLen) buffer[0] += 0x10;
|
||||
if(flash) buffer[0] += 0x08;
|
||||
if(halfMsg) buffer[0] += 0x04;
|
||||
if(flash) buffer[0] += 0x08;
|
||||
if(halfMsg) buffer[0] += 0x04;
|
||||
buffer[0] += 0x01; // Always ASCII
|
||||
|
||||
Array.Copy(firstHalfBytes, 0, buffer, 1, 8);
|
||||
Array.Copy(firstHalfBytes, 0, buffer, 1, 8);
|
||||
Array.Copy(secondHalfBytes, 0, buffer, 9, 8);
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.FujitsuDisplay;
|
||||
|
||||
@@ -46,22 +46,22 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
/// <param name="lba">Start block address.</param>
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
public bool HlDtStReadRawDvd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint transferLength,
|
||||
uint timeout, out double duration)
|
||||
public bool HlDtStReadRawDvd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint transferLength,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
buffer = new byte[2064 * transferLength];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.HlDtStVendor;
|
||||
cdb[1] = 0x48;
|
||||
cdb[2] = 0x49;
|
||||
cdb[3] = 0x54;
|
||||
cdb[4] = 0x01;
|
||||
cdb[6] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(lba & 0xFF);
|
||||
cdb[0] = (byte)ScsiCommands.HlDtStVendor;
|
||||
cdb[1] = 0x48;
|
||||
cdb[2] = 0x49;
|
||||
cdb[3] = 0x54;
|
||||
cdb[4] = 0x01;
|
||||
cdb[6] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(lba & 0xFF);
|
||||
cdb[10] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[11] = (byte)(buffer.Length & 0xFF);
|
||||
|
||||
|
||||
@@ -48,8 +48,9 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="pba">If set to <c>true</c> address contain physical block address.</param>
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool HpReadLong(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address, ushort blockBytes,
|
||||
bool pba, uint timeout, out double duration)
|
||||
public bool HpReadLong(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address,
|
||||
ushort blockBytes,
|
||||
bool pba, uint timeout, out double duration)
|
||||
{
|
||||
return HpReadLong(out buffer, out senseBuffer, relAddr, address, 0, blockBytes, pba, false, timeout,
|
||||
out duration);
|
||||
@@ -72,8 +73,9 @@ namespace DiscImageChef.Devices
|
||||
/// </param>
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool HpReadLong(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address,
|
||||
ushort transferLen, ushort blockBytes, bool pba, bool sectorCount, uint timeout,
|
||||
public bool HpReadLong(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address,
|
||||
ushort transferLen, ushort blockBytes, bool pba, bool sectorCount,
|
||||
uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
@@ -82,12 +84,12 @@ namespace DiscImageChef.Devices
|
||||
cdb[0] = (byte)ScsiCommands.ReadLong;
|
||||
if(relAddr) cdb[1] += 0x01;
|
||||
cdb[2] = (byte)((address & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(address & 0xFF);
|
||||
cdb[7] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(transferLen & 0xFF);
|
||||
if(pba) cdb[9] += 0x80;
|
||||
if(pba) cdb[9] += 0x80;
|
||||
if(sectorCount) cdb[9] += 0x40;
|
||||
|
||||
buffer = sectorCount ? new byte[blockBytes * transferLen] : new byte[transferLen];
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace DiscImageChef.Devices
|
||||
public bool KreonDeprecatedUnlock(out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.KreonCommand;
|
||||
@@ -111,7 +111,7 @@ namespace DiscImageChef.Devices
|
||||
public bool KreonSetLockState(out byte[] senseBuffer, KreonLockStates state, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.KreonCommand;
|
||||
@@ -141,7 +141,7 @@ namespace DiscImageChef.Devices
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[26];
|
||||
features = 0;
|
||||
|
||||
@@ -214,22 +214,22 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="buffer">The SS sector.</param>
|
||||
/// <param name="requestNumber">Request number.</param>
|
||||
public bool KreonExtractSs(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration,
|
||||
byte requestNumber = 0x00)
|
||||
byte requestNumber = 0x00)
|
||||
{
|
||||
buffer = new byte[2048];
|
||||
byte[] cdb = new byte[12];
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.KreonSsCommand;
|
||||
cdb[1] = 0x00;
|
||||
cdb[2] = 0xFF;
|
||||
cdb[3] = 0x02;
|
||||
cdb[4] = 0xFD;
|
||||
cdb[5] = 0xFF;
|
||||
cdb[6] = 0xFE;
|
||||
cdb[7] = 0x00;
|
||||
cdb[8] = 0x08;
|
||||
cdb[9] = 0x00;
|
||||
cdb[0] = (byte)ScsiCommands.KreonSsCommand;
|
||||
cdb[1] = 0x00;
|
||||
cdb[2] = 0xFF;
|
||||
cdb[3] = 0x02;
|
||||
cdb[4] = 0xFD;
|
||||
cdb[5] = 0xFF;
|
||||
cdb[6] = 0xFE;
|
||||
cdb[7] = 0x00;
|
||||
cdb[8] = 0x08;
|
||||
cdb[9] = 0x00;
|
||||
cdb[10] = requestNumber;
|
||||
cdb[11] = 0xC0;
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="startingFeatureNumber">Feature number where the feature list should start from</param>
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber,
|
||||
public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return GetConfiguration(out buffer, out senseBuffer, startingFeatureNumber, MmcGetConfigurationRt.All,
|
||||
@@ -78,19 +78,20 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
/// <param name="startingFeatureNumber">Starting Feature number.</param>
|
||||
/// <param name="rt">Return type, <see cref="MmcGetConfigurationRt" />.</param>
|
||||
public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer, ushort startingFeatureNumber,
|
||||
MmcGetConfigurationRt rt, uint timeout, out double duration)
|
||||
public bool GetConfiguration(out byte[] buffer, out byte[] senseBuffer,
|
||||
ushort startingFeatureNumber,
|
||||
MmcGetConfigurationRt rt, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
buffer = new byte[8];
|
||||
byte[] cdb = new byte[10];
|
||||
buffer = new byte[8];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.GetConfiguration;
|
||||
cdb[1] = (byte)((byte)rt & 0x03);
|
||||
cdb[1] = (byte)((byte)rt & 0x03);
|
||||
cdb[2] = (byte)((startingFeatureNumber & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(startingFeatureNumber & 0xFF);
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
cdb[3] = (byte)(startingFeatureNumber & 0xFF);
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
cdb[9] = 0;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -100,10 +101,10 @@ namespace DiscImageChef.Devices
|
||||
if(sense) return true;
|
||||
|
||||
ushort confLength = (ushort)((buffer[2] << 8) + buffer[3] + 4);
|
||||
buffer = new byte[confLength];
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
senseBuffer = new byte[32];
|
||||
buffer = new byte[confLength];
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out sense);
|
||||
@@ -127,26 +128,26 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="format">Which disc structure are we requesting</param>
|
||||
/// <param name="agid">AGID used in medium copy protection</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool ReadDiscStructure(out byte[] buffer, out byte[] senseBuffer, MmcDiscStructureMediaType mediaType,
|
||||
uint address, byte layerNumber, MmcDiscStructureFormat format,
|
||||
public bool ReadDiscStructure(out byte[] buffer, out byte[] senseBuffer, MmcDiscStructureMediaType mediaType,
|
||||
uint address, byte layerNumber, MmcDiscStructureFormat format,
|
||||
byte agid,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
buffer = new byte[8];
|
||||
byte[] cdb = new byte[12];
|
||||
buffer = new byte[8];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadDiscStructure;
|
||||
cdb[1] = (byte)((byte)mediaType & 0x0F);
|
||||
cdb[2] = (byte)((address & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(address & 0xFF);
|
||||
cdb[2] = (byte)((address & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(address & 0xFF);
|
||||
cdb[6] = layerNumber;
|
||||
cdb[7] = (byte)format;
|
||||
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(buffer.Length & 0xFF);
|
||||
cdb[10] = (byte)((agid & 0x03) << 6);
|
||||
cdb[9] = (byte)(buffer.Length & 0xFF);
|
||||
cdb[10] = (byte)((agid & 0x03) << 6);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out bool sense);
|
||||
@@ -155,10 +156,9 @@ namespace DiscImageChef.Devices
|
||||
if(sense) return true;
|
||||
|
||||
ushort strctLength = (ushort)((buffer[0] << 8) + buffer[1] + 2);
|
||||
|
||||
|
||||
// WORKAROUND: Some drives return incorrect length information. As these structures are fixed length just apply known length.
|
||||
if(mediaType == MmcDiscStructureMediaType.Bd)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case MmcDiscStructureFormat.DiscInformation:
|
||||
@@ -180,12 +180,10 @@ namespace DiscImageChef.Devices
|
||||
buffer = new byte[strctLength];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
buffer = new byte[strctLength];
|
||||
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(buffer.Length & 0xFF);
|
||||
senseBuffer = new byte[32];
|
||||
else buffer = new byte[strctLength];
|
||||
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(buffer.Length & 0xFF);
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out sense);
|
||||
@@ -319,27 +317,27 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="trackSessionNumber">Track/Session number</param>
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool ReadTocPmaAtip(out byte[] buffer, out byte[] senseBuffer, bool msf, byte format,
|
||||
byte trackSessionNumber, uint timeout, out double duration)
|
||||
public bool ReadTocPmaAtip(out byte[] buffer, out byte[] senseBuffer, bool msf, byte format,
|
||||
byte trackSessionNumber, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
byte[] cdb = new byte[10];
|
||||
|
||||
byte[] tmpBuffer = (format & 0x0F) == 5 ? new byte[32768] : new byte[1024];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadTocPmaAtip;
|
||||
cdb[0] = (byte)ScsiCommands.ReadTocPmaAtip;
|
||||
if(msf) cdb[1] = 0x02;
|
||||
cdb[2] = (byte)(format & 0x0F);
|
||||
cdb[6] = trackSessionNumber;
|
||||
cdb[7] = (byte)((tmpBuffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(tmpBuffer.Length & 0xFF);
|
||||
cdb[2] = (byte)(format & 0x0F);
|
||||
cdb[6] = trackSessionNumber;
|
||||
cdb[7] = (byte)((tmpBuffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(tmpBuffer.Length & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref tmpBuffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
uint strctLength = (uint)((tmpBuffer[0] << 8) + tmpBuffer[1] + 2);
|
||||
buffer = new byte[strctLength];
|
||||
buffer = new byte[strctLength];
|
||||
|
||||
if(buffer.Length <= tmpBuffer.Length)
|
||||
{
|
||||
@@ -386,23 +384,23 @@ namespace DiscImageChef.Devices
|
||||
MmcDiscInformationDataTypes dataType,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
byte[] tmpBuffer = new byte[804];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadDiscInformation;
|
||||
cdb[1] = (byte)dataType;
|
||||
cdb[7] = (byte)((tmpBuffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(tmpBuffer.Length & 0xFF);
|
||||
cdb[8] = (byte)(tmpBuffer.Length & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref tmpBuffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out bool sense);
|
||||
Error = LastError != 0;
|
||||
|
||||
uint strctLength = (uint)((tmpBuffer[0] << 8) + tmpBuffer[1] + 2);
|
||||
uint strctLength = (uint)((tmpBuffer[0] << 8) + tmpBuffer[1] + 2);
|
||||
if(strctLength > tmpBuffer.Length) strctLength = (uint)tmpBuffer.Length;
|
||||
|
||||
buffer = new byte[strctLength];
|
||||
buffer = new byte[strctLength];
|
||||
Array.Copy(tmpBuffer, 0, buffer, 0, buffer.Length);
|
||||
|
||||
DicConsole.DebugWriteLine("SCSI Device", "READ DISC INFORMATION took {0} ms.", duration);
|
||||
@@ -430,32 +428,34 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param>
|
||||
/// <param name="c2Error">C2 error options.</param>
|
||||
/// <param name="subchannel">Subchannel selection.</param>
|
||||
public bool ReadCd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
uint transferLength,
|
||||
MmcSectorTypes expectedSectorType, bool dap, bool relAddr, bool sync,
|
||||
MmcHeaderCodes headerCodes, bool userData, bool edcEcc, MmcErrorField c2Error,
|
||||
MmcSubchannel subchannel, uint timeout, out double duration)
|
||||
public bool ReadCd(out byte[] buffer, out byte[] senseBuffer, uint lba,
|
||||
uint blockSize, uint transferLength,
|
||||
MmcSectorTypes expectedSectorType, bool dap, bool relAddr,
|
||||
bool sync,
|
||||
MmcHeaderCodes headerCodes, bool userData, bool edcEcc,
|
||||
MmcErrorField c2Error,
|
||||
MmcSubchannel subchannel, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadCd;
|
||||
cdb[1] = (byte)((byte)expectedSectorType << 2);
|
||||
if(dap) cdb[1] += 0x02;
|
||||
if(relAddr) cdb[1] += 0x01;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[6] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[7] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(transferLength & 0xFF);
|
||||
cdb[9] = (byte)((byte)c2Error << 1);
|
||||
cdb[9] += (byte)((byte)headerCodes << 5);
|
||||
cdb[0] = (byte)ScsiCommands.ReadCd;
|
||||
cdb[1] = (byte)((byte)expectedSectorType << 2);
|
||||
if(dap) cdb[1] += 0x02;
|
||||
if(relAddr) cdb[1] += 0x01;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[6] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[7] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(transferLength & 0xFF);
|
||||
cdb[9] = (byte)((byte)c2Error << 1);
|
||||
cdb[9] += (byte)((byte)headerCodes << 5);
|
||||
if(sync) cdb[9] += 0x80;
|
||||
if(userData) cdb[9] += 0x10;
|
||||
if(edcEcc) cdb[9] += 0x08;
|
||||
cdb[10] = (byte)subchannel;
|
||||
cdb[10] = (byte)subchannel;
|
||||
|
||||
buffer = new byte[blockSize * transferLength];
|
||||
|
||||
@@ -487,32 +487,32 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param>
|
||||
/// <param name="c2Error">C2 error options.</param>
|
||||
/// <param name="subchannel">Subchannel selection.</param>
|
||||
public bool ReadCdMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf,
|
||||
uint endMsf, uint blockSize,
|
||||
MmcSectorTypes expectedSectorType, bool dap, bool sync,
|
||||
public bool ReadCdMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf,
|
||||
uint endMsf, uint blockSize,
|
||||
MmcSectorTypes expectedSectorType, bool dap, bool sync,
|
||||
MmcHeaderCodes headerCodes,
|
||||
bool userData, bool edcEcc, MmcErrorField c2Error,
|
||||
bool userData, bool edcEcc, MmcErrorField c2Error,
|
||||
MmcSubchannel subchannel, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdMsf;
|
||||
cdb[1] = (byte)((byte)expectedSectorType << 2);
|
||||
if(dap) cdb[1] += 0x02;
|
||||
cdb[3] = (byte)((startMsf & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((startMsf & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(startMsf & 0xFF);
|
||||
cdb[6] = (byte)((endMsf & 0xFF0000) >> 16);
|
||||
cdb[7] = (byte)((endMsf & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(endMsf & 0xFF);
|
||||
cdb[9] = (byte)((byte)c2Error << 1);
|
||||
cdb[9] += (byte)((byte)headerCodes << 5);
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdMsf;
|
||||
cdb[1] = (byte)((byte)expectedSectorType << 2);
|
||||
if(dap) cdb[1] += 0x02;
|
||||
cdb[3] = (byte)((startMsf & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((startMsf & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(startMsf & 0xFF);
|
||||
cdb[6] = (byte)((endMsf & 0xFF0000) >> 16);
|
||||
cdb[7] = (byte)((endMsf & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(endMsf & 0xFF);
|
||||
cdb[9] = (byte)((byte)c2Error << 1);
|
||||
cdb[9] += (byte)((byte)headerCodes << 5);
|
||||
if(sync) cdb[9] += 0x80;
|
||||
if(userData) cdb[9] += 0x10;
|
||||
if(edcEcc) cdb[9] += 0x08;
|
||||
cdb[10] = (byte)subchannel;
|
||||
cdb[10] = (byte)subchannel;
|
||||
|
||||
uint transferLength = (uint)((cdb[6] - cdb[3]) * 60 * 75 + (cdb[7] - cdb[4]) * 75 + (cdb[8] - cdb[5]));
|
||||
|
||||
@@ -540,11 +540,11 @@ namespace DiscImageChef.Devices
|
||||
public bool PreventAllowMediumRemoval(out byte[] senseBuffer, bool persistent, bool prevent, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PreventAllowMediumRemoval;
|
||||
cdb[0] = (byte)ScsiCommands.PreventAllowMediumRemoval;
|
||||
if(prevent) cdb[4] += 0x01;
|
||||
if(persistent) cdb[4] += 0x02;
|
||||
|
||||
@@ -577,15 +577,15 @@ namespace DiscImageChef.Devices
|
||||
return StartStopUnit(out senseBuffer, false, 0, 0, false, false, false, timeout, out duration);
|
||||
}
|
||||
|
||||
public bool StartStopUnit(out byte[] senseBuffer, bool immediate, byte formatLayer, byte powerConditions,
|
||||
bool changeFormatLayer, bool loadEject, bool start, uint timeout,
|
||||
public bool StartStopUnit(out byte[] senseBuffer, bool immediate, byte formatLayer, byte powerConditions,
|
||||
bool changeFormatLayer, bool loadEject, bool start, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.StartStopUnit;
|
||||
cdb[0] = (byte)ScsiCommands.StartStopUnit;
|
||||
if(immediate) cdb[1] += 0x01;
|
||||
if(changeFormatLayer)
|
||||
{
|
||||
@@ -613,15 +613,15 @@ namespace DiscImageChef.Devices
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
mcn = null;
|
||||
byte[] cdb = new byte[10];
|
||||
mcn = null;
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadSubChannel;
|
||||
cdb[1] = 0;
|
||||
cdb[2] = 0x40;
|
||||
cdb[3] = 0x02;
|
||||
cdb[7] = (23 & 0xFF00) >> 8;
|
||||
cdb[8] = 23 & 0xFF;
|
||||
cdb[8] = 23 & 0xFF;
|
||||
|
||||
buffer = new byte[23];
|
||||
|
||||
@@ -636,12 +636,13 @@ namespace DiscImageChef.Devices
|
||||
return sense;
|
||||
}
|
||||
|
||||
public bool ReadIsrc(byte trackNumber, out string isrc, out byte[] buffer, out byte[] senseBuffer, uint timeout,
|
||||
out double duration)
|
||||
public bool ReadIsrc(byte trackNumber, out string isrc, out byte[] buffer, out byte[] senseBuffer,
|
||||
uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
isrc = null;
|
||||
byte[] cdb = new byte[10];
|
||||
isrc = null;
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadSubChannel;
|
||||
cdb[1] = 0;
|
||||
@@ -649,7 +650,7 @@ namespace DiscImageChef.Devices
|
||||
cdb[3] = 0x03;
|
||||
cdb[6] = trackNumber;
|
||||
cdb[7] = (23 & 0xFF00) >> 8;
|
||||
cdb[8] = 23 & 0xFF;
|
||||
cdb[8] = 23 & 0xFF;
|
||||
|
||||
buffer = new byte[23];
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.NecReadCdDa;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[7] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(transferLength & 0xFF);
|
||||
|
||||
@@ -48,21 +48,21 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
/// <param name="blockSize">Block size.</param>
|
||||
/// <param name="subchannel">Subchannel selection.</param>
|
||||
public bool PioneerReadCdDa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
uint transferLength, PioneerSubchannel subchannel, uint timeout,
|
||||
public bool PioneerReadCdDa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
uint transferLength, PioneerSubchannel subchannel, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdDa;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[7] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(transferLength & 0xFF);
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdDa;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[7] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(transferLength & 0xFF);
|
||||
cdb[10] = (byte)subchannel;
|
||||
|
||||
buffer = new byte[blockSize * transferLength];
|
||||
@@ -88,19 +88,21 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="endMsf">End MM:SS:FF of read encoded as 0x00MMSSFF.</param>
|
||||
/// <param name="blockSize">Block size.</param>
|
||||
/// <param name="subchannel">Subchannel selection.</param>
|
||||
public bool PioneerReadCdDaMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf, uint endMsf,
|
||||
uint blockSize, PioneerSubchannel subchannel, uint timeout, out double duration)
|
||||
public bool PioneerReadCdDaMsf(out byte[] buffer, out byte[] senseBuffer, uint startMsf,
|
||||
uint endMsf,
|
||||
uint blockSize, PioneerSubchannel subchannel, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdDaMsf;
|
||||
cdb[3] = (byte)((startMsf & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((startMsf & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(startMsf & 0xFF);
|
||||
cdb[7] = (byte)((endMsf & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((endMsf & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(endMsf & 0xFF);
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdDaMsf;
|
||||
cdb[3] = (byte)((startMsf & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((startMsf & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(startMsf & 0xFF);
|
||||
cdb[7] = (byte)((endMsf & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((endMsf & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(endMsf & 0xFF);
|
||||
cdb[10] = (byte)subchannel;
|
||||
|
||||
uint transferLength = (uint)((cdb[7] - cdb[3]) * 60 * 75 + (cdb[8] - cdb[4]) * 75 + (cdb[9] - cdb[5]));
|
||||
@@ -130,19 +132,20 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="wholeSector">If set to <c>true</c>, returns all 2352 bytes of sector data.</param>
|
||||
/// <param name="lba">Start block address.</param>
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
public bool PioneerReadCdXa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint transferLength,
|
||||
bool errorFlags, bool wholeSector, uint timeout, out double duration)
|
||||
public bool PioneerReadCdXa(out byte[] buffer, out byte[] senseBuffer, uint lba,
|
||||
uint transferLength,
|
||||
bool errorFlags, bool wholeSector, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdXa;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[7] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(transferLength & 0xFF);
|
||||
|
||||
if(errorFlags)
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="pba">If set to <c>true</c> address contain physical block address.</param>
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool PlasmonReadLong(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address,
|
||||
ushort blockBytes, bool pba, uint timeout, out double duration)
|
||||
public bool PlasmonReadLong(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address,
|
||||
ushort blockBytes, bool pba, uint timeout, out double duration)
|
||||
{
|
||||
return HpReadLong(out buffer, out senseBuffer, relAddr, address, 0, blockBytes, pba, false, timeout,
|
||||
out duration);
|
||||
@@ -72,12 +72,13 @@ namespace DiscImageChef.Devices
|
||||
/// </param>
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool PlasmonReadLong(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address,
|
||||
ushort transferLen, ushort blockBytes, bool pba, bool sectorCount, uint timeout,
|
||||
public bool PlasmonReadLong(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address,
|
||||
ushort transferLen, ushort blockBytes, bool pba, bool sectorCount,
|
||||
uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
return HpReadLong(out buffer, out senseBuffer, relAddr, address, transferLen, blockBytes, pba, sectorCount,
|
||||
timeout, out duration);
|
||||
timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -90,16 +91,16 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="pba">If set to <c>true</c> address contain a physical block address.</param>
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool PlasmonReadSectorLocation(out byte[] buffer, out byte[] senseBuffer, uint address, bool pba,
|
||||
uint timeout, out double duration)
|
||||
public bool PlasmonReadSectorLocation(out byte[] buffer, out byte[] senseBuffer, uint address, bool pba,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlasmonReadSectorLocation;
|
||||
cdb[2] = (byte)((address & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(address & 0xFF);
|
||||
if(pba) cdb[9] += 0x80;
|
||||
|
||||
|
||||
@@ -49,22 +49,22 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
/// <param name="blockSize">Block size.</param>
|
||||
/// <param name="subchannel">Subchannel selection.</param>
|
||||
public bool PlextorReadCdDa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
uint transferLength, PlextorSubchannel subchannel, uint timeout,
|
||||
public bool PlextorReadCdDa(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
uint transferLength, PlextorSubchannel subchannel, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdDa;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[6] = (byte)((transferLength & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(transferLength & 0xFF);
|
||||
cdb[0] = (byte)ScsiCommands.ReadCdDa;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[6] = (byte)((transferLength & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(transferLength & 0xFF);
|
||||
cdb[10] = (byte)subchannel;
|
||||
|
||||
buffer = new byte[blockSize * transferLength];
|
||||
@@ -88,8 +88,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
/// <param name="lba">Start block address.</param>
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
public bool PlextorReadRawDvd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint transferLength,
|
||||
uint timeout, out double duration)
|
||||
public bool PlextorReadRawDvd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint transferLength,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
@@ -98,10 +98,10 @@ namespace DiscImageChef.Devices
|
||||
cdb[0] = (byte)ScsiCommands.ReadBuffer;
|
||||
cdb[1] = 0x02;
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[3] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[4] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(buffer.Length & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -123,7 +123,7 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorReadEepromCdr(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[256];
|
||||
buffer = new byte[256];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorReadEeprom(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[512];
|
||||
buffer = new byte[512];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
@@ -175,10 +175,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">How many bytes are in the EEPROM block</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorReadEepromBlock(out byte[] buffer, out byte[] senseBuffer, byte block, ushort blockSize,
|
||||
uint timeout, out double duration)
|
||||
public bool PlextorReadEepromBlock(out byte[] buffer, out byte[] senseBuffer, byte block, ushort blockSize,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[blockSize];
|
||||
buffer = new byte[blockSize];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
@@ -208,15 +208,15 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorGetSpeeds(out byte[] senseBuffer, out ushort selected, out ushort max, out ushort last,
|
||||
uint timeout, out double duration)
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
byte[] buf = new byte[10];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
selected = 0;
|
||||
max = 0;
|
||||
last = 0;
|
||||
max = 0;
|
||||
last = 0;
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlextorPoweRec;
|
||||
cdb[9] = (byte)buf.Length;
|
||||
@@ -230,9 +230,9 @@ namespace DiscImageChef.Devices
|
||||
if(sense || Error) return sense;
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
selected = BigEndianBitConverter.ToUInt16(buf, 4);
|
||||
max = BigEndianBitConverter.ToUInt16(buf, 6);
|
||||
last = BigEndianBitConverter.ToUInt16(buf, 8);
|
||||
selected = BigEndianBitConverter.ToUInt16(buf, 4);
|
||||
max = BigEndianBitConverter.ToUInt16(buf, 6);
|
||||
last = BigEndianBitConverter.ToUInt16(buf, 8);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -254,7 +254,7 @@ namespace DiscImageChef.Devices
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
enabled = false;
|
||||
speed = 0;
|
||||
speed = 0;
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend2;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
@@ -269,8 +269,8 @@ namespace DiscImageChef.Devices
|
||||
if(sense || Error) return sense;
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
enabled = buf[2] != 0;
|
||||
speed = BigEndianBitConverter.ToUInt16(buf, 4);
|
||||
enabled = buf[2] != 0;
|
||||
speed = BigEndianBitConverter.ToUInt16(buf, 4);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -285,14 +285,14 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorGetSilentMode(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[8];
|
||||
buffer = new byte[8];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.Silent;
|
||||
cdb[3] = 4;
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.Silent;
|
||||
cdb[3] = 4;
|
||||
cdb[10] = (byte)buffer.Length;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -314,13 +314,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorGetGigaRec(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[8];
|
||||
buffer = new byte[8];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.GigaRec;
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.GigaRec;
|
||||
cdb[10] = (byte)buffer.Length;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -344,17 +344,17 @@ namespace DiscImageChef.Devices
|
||||
public bool PlextorGetVariRec(out byte[] buffer, out byte[] senseBuffer, bool dvd, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = new byte[8];
|
||||
buffer = new byte[8];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.VariRec;
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.VariRec;
|
||||
cdb[10] = (byte)buffer.Length;
|
||||
|
||||
if(dvd) cdb[3] = 0x12;
|
||||
else cdb[3] = 0x02;
|
||||
else cdb[3] = 0x02;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out bool sense);
|
||||
@@ -375,12 +375,12 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorGetSecuRec(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[8];
|
||||
buffer = new byte[8];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[2] = (byte)PlextorSubCommands.SecuRec;
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[2] = (byte)PlextorSubCommands.SecuRec;
|
||||
cdb[10] = (byte)buffer.Length;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -402,13 +402,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorGetSpeedRead(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[8];
|
||||
buffer = new byte[8];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.SpeedRead;
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.SpeedRead;
|
||||
cdb[10] = (byte)buffer.Length;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -430,7 +430,7 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool PlextorGetHiding(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[8];
|
||||
buffer = new byte[8];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
@@ -460,7 +460,7 @@ namespace DiscImageChef.Devices
|
||||
public bool PlextorGetBitsetting(out byte[] buffer, out byte[] senseBuffer, bool dualLayer, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = new byte[8];
|
||||
buffer = new byte[8];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
@@ -470,7 +470,7 @@ namespace DiscImageChef.Devices
|
||||
cdb[9] = (byte)buffer.Length;
|
||||
|
||||
if(dualLayer) cdb[3] = (byte)PlextorSubCommands.BitSetRdl;
|
||||
else cdb[3] = (byte)PlextorSubCommands.BitSetR;
|
||||
else cdb[3] = (byte)PlextorSubCommands.BitSetR;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out bool sense);
|
||||
@@ -492,13 +492,13 @@ namespace DiscImageChef.Devices
|
||||
public bool PlextorGetTestWriteDvdPlus(out byte[] buffer, out byte[] senseBuffer, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = new byte[8];
|
||||
buffer = new byte[8];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.TestWriteDvdPlus;
|
||||
cdb[0] = (byte)ScsiCommands.PlextorExtend;
|
||||
cdb[1] = (byte)PlextorSubCommands.GetMode;
|
||||
cdb[2] = (byte)PlextorSubCommands.TestWriteDvdPlus;
|
||||
cdb[10] = (byte)buffer.Length;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
|
||||
@@ -64,20 +64,20 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="lba">Starting block.</param>
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
public bool Read6(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, byte transferLength,
|
||||
uint timeout, out double duration)
|
||||
public bool Read6(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, byte transferLength,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read6;
|
||||
cdb[1] = (byte)((lba & 0x1F0000) >> 16);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(lba & 0xFF);
|
||||
cdb[4] = transferLength;
|
||||
|
||||
if(transferLength == 0) buffer = new byte[256 * blockSize];
|
||||
else buffer = new byte[transferLength * blockSize];
|
||||
if(transferLength == 0) buffer = new byte[256 * blockSize];
|
||||
else buffer = new byte[transferLength * blockSize];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out bool sense);
|
||||
@@ -111,23 +111,25 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="groupNumber">Group number where attributes associated with this command should be collected.</param>
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
/// <param name="relAddr">If set to <c>true</c> address is relative to current position.</param>
|
||||
public bool Read10(out byte[] buffer, out byte[] senseBuffer, byte rdprotect, bool dpo, bool fua, bool fuaNv,
|
||||
bool relAddr, uint lba, uint blockSize, byte groupNumber, ushort transferLength,
|
||||
uint timeout, out double duration)
|
||||
public bool Read10(out byte[] buffer, out byte[] senseBuffer, byte rdprotect, bool dpo, bool fua,
|
||||
bool fuaNv,
|
||||
bool relAddr, uint lba, uint blockSize, byte groupNumber,
|
||||
ushort transferLength,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read10;
|
||||
cdb[1] = (byte)((rdprotect & 0x07) << 5);
|
||||
if(dpo) cdb[1] += 0x10;
|
||||
if(fua) cdb[1] += 0x08;
|
||||
if(fuaNv) cdb[1] += 0x02;
|
||||
if(dpo) cdb[1] += 0x10;
|
||||
if(fua) cdb[1] += 0x08;
|
||||
if(fuaNv) cdb[1] += 0x02;
|
||||
if(relAddr) cdb[1] += 0x01;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[6] = (byte)(groupNumber & 0x1F);
|
||||
cdb[7] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(transferLength & 0xFF);
|
||||
@@ -167,28 +169,30 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
/// <param name="streaming">If set to <c>true</c> the stream playback operation should be used (MMC only).</param>
|
||||
/// <param name="relAddr">If set to <c>true</c> address is relative to current position.</param>
|
||||
public bool Read12(out byte[] buffer, out byte[] senseBuffer, byte rdprotect, bool dpo, bool fua, bool fuaNv,
|
||||
bool relAddr, uint lba, uint blockSize, byte groupNumber, uint transferLength,
|
||||
bool streaming, uint timeout, out double duration)
|
||||
public bool Read12(out byte[] buffer, out byte[] senseBuffer, byte rdprotect, bool dpo,
|
||||
bool fua, bool fuaNv,
|
||||
bool relAddr, uint lba, uint blockSize, byte groupNumber,
|
||||
uint transferLength,
|
||||
bool streaming, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[12];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read12;
|
||||
cdb[1] = (byte)((rdprotect & 0x07) << 5);
|
||||
if(dpo) cdb[1] += 0x10;
|
||||
if(fua) cdb[1] += 0x08;
|
||||
if(fuaNv) cdb[1] += 0x02;
|
||||
if(dpo) cdb[1] += 0x10;
|
||||
if(fua) cdb[1] += 0x08;
|
||||
if(fuaNv) cdb[1] += 0x02;
|
||||
if(relAddr) cdb[1] += 0x01;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[6] = (byte)((transferLength & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(transferLength & 0xFF);
|
||||
cdb[10] = (byte)(groupNumber & 0x1F);
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[6] = (byte)((transferLength & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(transferLength & 0xFF);
|
||||
cdb[10] = (byte)(groupNumber & 0x1F);
|
||||
if(streaming) cdb[10] += 0x80;
|
||||
|
||||
buffer = new byte[transferLength * blockSize];
|
||||
@@ -225,32 +229,34 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="groupNumber">Group number where attributes associated with this command should be collected.</param>
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
/// <param name="streaming">If set to <c>true</c> the stream playback operation should be used (MMC only).</param>
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, byte rdprotect, bool dpo, bool fua, bool fuaNv,
|
||||
ulong lba, uint blockSize, byte groupNumber, uint transferLength, bool streaming,
|
||||
uint timeout, out double duration)
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, byte rdprotect, bool dpo, bool fua,
|
||||
bool fuaNv,
|
||||
ulong lba, uint blockSize, byte groupNumber, uint transferLength,
|
||||
bool streaming,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[16];
|
||||
byte[] cdb = new byte[16];
|
||||
byte[] lbaBytes = BitConverter.GetBytes(lba);
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read16;
|
||||
cdb[1] = (byte)((rdprotect & 0x07) << 5);
|
||||
if(dpo) cdb[1] += 0x10;
|
||||
if(fua) cdb[1] += 0x08;
|
||||
if(dpo) cdb[1] += 0x10;
|
||||
if(fua) cdb[1] += 0x08;
|
||||
if(fuaNv) cdb[1] += 0x02;
|
||||
cdb[2] = lbaBytes[7];
|
||||
cdb[3] = lbaBytes[6];
|
||||
cdb[4] = lbaBytes[5];
|
||||
cdb[5] = lbaBytes[4];
|
||||
cdb[6] = lbaBytes[3];
|
||||
cdb[7] = lbaBytes[2];
|
||||
cdb[8] = lbaBytes[1];
|
||||
cdb[9] = lbaBytes[0];
|
||||
cdb[2] = lbaBytes[7];
|
||||
cdb[3] = lbaBytes[6];
|
||||
cdb[4] = lbaBytes[5];
|
||||
cdb[5] = lbaBytes[4];
|
||||
cdb[6] = lbaBytes[3];
|
||||
cdb[7] = lbaBytes[2];
|
||||
cdb[8] = lbaBytes[1];
|
||||
cdb[9] = lbaBytes[0];
|
||||
cdb[10] = (byte)((transferLength & 0xFF000000) >> 24);
|
||||
cdb[11] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[12] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[11] = (byte)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[12] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[13] = (byte)(transferLength & 0xFF);
|
||||
cdb[14] = (byte)(groupNumber & 0x1F);
|
||||
cdb[14] = (byte)(groupNumber & 0x1F);
|
||||
if(streaming) cdb[14] += 0x80;
|
||||
|
||||
buffer = new byte[transferLength * blockSize];
|
||||
@@ -279,8 +285,9 @@ namespace DiscImageChef.Devices
|
||||
/// How many bytes to read. If the number is not exactly the drive's size, the command will
|
||||
/// fail and incidate a delta of the size in SENSE.
|
||||
/// </param>
|
||||
public bool ReadLong10(out byte[] buffer, out byte[] senseBuffer, bool correct, bool relAddr, uint lba,
|
||||
ushort transferBytes, uint timeout, out double duration)
|
||||
public bool ReadLong10(out byte[] buffer, out byte[] senseBuffer, bool correct, bool relAddr,
|
||||
uint lba,
|
||||
ushort transferBytes, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
@@ -289,8 +296,8 @@ namespace DiscImageChef.Devices
|
||||
if(correct) cdb[1] += 0x02;
|
||||
if(relAddr) cdb[1] += 0x01;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[7] = (byte)((transferBytes & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(transferBytes & 0xFF);
|
||||
@@ -320,23 +327,23 @@ namespace DiscImageChef.Devices
|
||||
/// How many bytes to read. If the number is not exactly the drive's size, the command will
|
||||
/// fail and incidate a delta of the size in SENSE.
|
||||
/// </param>
|
||||
public bool ReadLong16(out byte[] buffer, out byte[] senseBuffer, bool correct, ulong lba, uint transferBytes,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadLong16(out byte[] buffer, out byte[] senseBuffer, bool correct, ulong lba, uint transferBytes,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[16];
|
||||
byte[] cdb = new byte[16];
|
||||
byte[] lbaBytes = BitConverter.GetBytes(lba);
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ServiceActionIn;
|
||||
cdb[1] = (byte)ScsiServiceActions.ReadLong16;
|
||||
cdb[2] = lbaBytes[7];
|
||||
cdb[3] = lbaBytes[6];
|
||||
cdb[4] = lbaBytes[5];
|
||||
cdb[5] = lbaBytes[4];
|
||||
cdb[6] = lbaBytes[3];
|
||||
cdb[7] = lbaBytes[2];
|
||||
cdb[8] = lbaBytes[1];
|
||||
cdb[9] = lbaBytes[0];
|
||||
cdb[0] = (byte)ScsiCommands.ServiceActionIn;
|
||||
cdb[1] = (byte)ScsiServiceActions.ReadLong16;
|
||||
cdb[2] = lbaBytes[7];
|
||||
cdb[3] = lbaBytes[6];
|
||||
cdb[4] = lbaBytes[5];
|
||||
cdb[5] = lbaBytes[4];
|
||||
cdb[6] = lbaBytes[3];
|
||||
cdb[7] = lbaBytes[2];
|
||||
cdb[8] = lbaBytes[1];
|
||||
cdb[9] = lbaBytes[0];
|
||||
cdb[12] = (byte)((transferBytes & 0xFF00) >> 8);
|
||||
cdb[13] = (byte)(transferBytes & 0xFF);
|
||||
if(correct) cdb[14] += 0x01;
|
||||
@@ -362,12 +369,12 @@ namespace DiscImageChef.Devices
|
||||
public bool Seek6(out byte[] senseBuffer, uint lba, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Seek6;
|
||||
cdb[1] = (byte)((lba & 0x1F0000) >> 16);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(lba & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
|
||||
@@ -389,13 +396,13 @@ namespace DiscImageChef.Devices
|
||||
public bool Seek10(out byte[] senseBuffer, uint lba, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
byte[] cdb = new byte[10];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Seek10;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
|
||||
|
||||
@@ -50,26 +50,28 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="cache">If set to <c>true</c> device can return cached data.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, ushort element,
|
||||
byte elementType, byte volume, byte partition, ushort firstAttribute, bool cache,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
ushort element,
|
||||
byte elementType, byte volume, byte partition,
|
||||
ushort firstAttribute, bool cache,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[256];
|
||||
byte[] cdb = new byte[16];
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadAttribute;
|
||||
cdb[1] = (byte)((byte)action & 0x1F);
|
||||
cdb[2] = (byte)((element & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(element & 0xFF);
|
||||
cdb[4] = (byte)(elementType & 0x0F);
|
||||
cdb[5] = volume;
|
||||
cdb[7] = partition;
|
||||
cdb[8] = (byte)((firstAttribute & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(firstAttribute & 0xFF);
|
||||
cdb[0] = (byte)ScsiCommands.ReadAttribute;
|
||||
cdb[1] = (byte)((byte)action & 0x1F);
|
||||
cdb[2] = (byte)((element & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(element & 0xFF);
|
||||
cdb[4] = (byte)(elementType & 0x0F);
|
||||
cdb[5] = volume;
|
||||
cdb[7] = partition;
|
||||
cdb[8] = (byte)((firstAttribute & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(firstAttribute & 0xFF);
|
||||
cdb[10] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
||||
cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[13] = (byte)(buffer.Length & 0xFF);
|
||||
if(cache) cdb[14] += 0x01;
|
||||
|
||||
@@ -80,11 +82,11 @@ namespace DiscImageChef.Devices
|
||||
if(sense) return true;
|
||||
|
||||
uint attrLen = (uint)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3] + 4);
|
||||
buffer = new byte[attrLen];
|
||||
cdb[10] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
||||
cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[13] = (byte)(buffer.Length & 0xFF);
|
||||
buffer = new byte[attrLen];
|
||||
cdb[10] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
||||
cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[13] = (byte)(buffer.Length & 0xFF);
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[36];
|
||||
buffer = new byte[36];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = {(byte)ScsiCommands.Inquiry, 0, 0, 0, 36, 0};
|
||||
|
||||
@@ -97,8 +97,8 @@ namespace DiscImageChef.Devices
|
||||
|
||||
byte pagesLength = (byte)(buffer[4] + 5);
|
||||
|
||||
cdb = new byte[] {(byte)ScsiCommands.Inquiry, 0, 0, 0, pagesLength, 0};
|
||||
buffer = new byte[pagesLength];
|
||||
cdb = new byte[] {(byte)ScsiCommands.Inquiry, 0, 0, 0, pagesLength, 0};
|
||||
buffer = new byte[pagesLength];
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -159,7 +159,7 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="page">The Extended Vital Product Data</param>
|
||||
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, byte page, uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[36];
|
||||
buffer = new byte[36];
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = {(byte)ScsiCommands.Inquiry, 1, page, 0, 36, 0};
|
||||
|
||||
@@ -174,8 +174,8 @@ namespace DiscImageChef.Devices
|
||||
|
||||
byte pagesLength = (byte)(buffer[3] + 4);
|
||||
|
||||
cdb = new byte[] {(byte)ScsiCommands.Inquiry, 1, page, 0, pagesLength, 0};
|
||||
buffer = new byte[pagesLength];
|
||||
cdb = new byte[] {(byte)ScsiCommands.Inquiry, 1, page, 0, pagesLength, 0};
|
||||
buffer = new byte[pagesLength];
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -197,7 +197,7 @@ namespace DiscImageChef.Devices
|
||||
public bool ScsiTestUnitReady(out byte[] senseBuffer, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = {(byte)ScsiCommands.TestUnitReady, 0, 0, 0, 0, 0};
|
||||
byte[] cdb = {(byte)ScsiCommands.TestUnitReady, 0, 0, 0, 0, 0};
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
|
||||
@@ -234,8 +234,9 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="dbd">If set to <c>true</c> device MUST not return any block descriptor.</param>
|
||||
/// <param name="pageControl">Page control.</param>
|
||||
/// <param name="pageCode">Page code.</param>
|
||||
public bool ModeSense6(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout, out double duration)
|
||||
public bool ModeSense6(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
return ModeSense6(out buffer, out senseBuffer, dbd, pageControl, pageCode, 0, timeout, out duration);
|
||||
}
|
||||
@@ -252,9 +253,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="pageControl">Page control.</param>
|
||||
/// <param name="pageCode">Page code.</param>
|
||||
/// <param name="subPageCode">Sub-page code.</param>
|
||||
public bool ModeSense6(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, byte subPageCode, uint timeout,
|
||||
out double duration)
|
||||
public bool ModeSense6(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, byte subPageCode,
|
||||
uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
@@ -264,9 +266,9 @@ namespace DiscImageChef.Devices
|
||||
if(dbd) cdb[1] = 0x08;
|
||||
cdb[2] |= (byte)pageControl;
|
||||
cdb[2] |= (byte)(pageCode & 0x3F);
|
||||
cdb[3] = subPageCode;
|
||||
cdb[4] = (byte)buffer.Length;
|
||||
cdb[5] = 0;
|
||||
cdb[3] = subPageCode;
|
||||
cdb[4] = (byte)buffer.Length;
|
||||
cdb[5] = 0;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out bool sense);
|
||||
@@ -275,8 +277,8 @@ namespace DiscImageChef.Devices
|
||||
if(sense) return true;
|
||||
|
||||
byte modeLength = (byte)(buffer[0] + 1);
|
||||
buffer = new byte[modeLength];
|
||||
cdb[4] = (byte)buffer.Length;
|
||||
buffer = new byte[modeLength];
|
||||
cdb[4] = (byte)buffer.Length;
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -299,8 +301,9 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="dbd">If set to <c>true</c> device MUST not return any block descriptor.</param>
|
||||
/// <param name="pageControl">Page control.</param>
|
||||
/// <param name="pageCode">Page code.</param>
|
||||
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout, out double duration)
|
||||
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
return ModeSense10(out buffer, out senseBuffer, false, dbd, pageControl, pageCode, 0, timeout,
|
||||
out duration);
|
||||
@@ -318,8 +321,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="pageControl">Page control.</param>
|
||||
/// <param name="pageCode">Page code.</param>
|
||||
/// <param name="llbaa">If set means 64-bit LBAs are accepted by the caller.</param>
|
||||
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool llbaa, bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout, out double duration)
|
||||
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool llbaa,
|
||||
bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
return ModeSense10(out buffer, out senseBuffer, llbaa, dbd, pageControl, pageCode, 0, timeout,
|
||||
out duration);
|
||||
@@ -338,9 +343,11 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="pageCode">Page code.</param>
|
||||
/// <param name="subPageCode">Sub-page code.</param>
|
||||
/// <param name="llbaa">If set means 64-bit LBAs are accepted by the caller.</param>
|
||||
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool llbaa, bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, byte subPageCode, uint timeout,
|
||||
out double duration)
|
||||
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool llbaa,
|
||||
bool dbd,
|
||||
ScsiModeSensePageControl pageControl, byte pageCode, byte subPageCode,
|
||||
uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
@@ -348,13 +355,13 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ModeSense10;
|
||||
if(llbaa) cdb[1] |= 0x10;
|
||||
if(dbd) cdb[1] |= 0x08;
|
||||
if(dbd) cdb[1] |= 0x08;
|
||||
cdb[2] |= (byte)pageControl;
|
||||
cdb[2] |= (byte)(pageCode & 0x3F);
|
||||
cdb[3] = subPageCode;
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
cdb[9] = 0;
|
||||
cdb[3] = subPageCode;
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
cdb[9] = 0;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
out bool sense);
|
||||
@@ -363,9 +370,9 @@ namespace DiscImageChef.Devices
|
||||
if(sense) return true;
|
||||
|
||||
ushort modeLength = (ushort)((buffer[0] << 8) + buffer[1] + 2);
|
||||
buffer = new byte[modeLength];
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
buffer = new byte[modeLength];
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -431,7 +438,7 @@ namespace DiscImageChef.Devices
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.PreventAllowMediumRemoval;
|
||||
@@ -470,8 +477,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="pmi">If set, it is requesting partial media capacity</param>
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
public bool ReadCapacity(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address, bool pmi,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadCapacity(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address, bool pmi,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
@@ -485,8 +492,8 @@ namespace DiscImageChef.Devices
|
||||
if(relAddr) cdb[1] = 0x01;
|
||||
|
||||
cdb[2] = (byte)((address & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(address & 0xFF);
|
||||
}
|
||||
|
||||
@@ -547,8 +554,8 @@ namespace DiscImageChef.Devices
|
||||
}
|
||||
|
||||
cdb[10] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
||||
cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[13] = (byte)(buffer.Length & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -577,8 +584,8 @@ namespace DiscImageChef.Devices
|
||||
cdb[0] = (byte)ScsiCommands.ReadSerialNumber;
|
||||
cdb[1] = 0x01;
|
||||
cdb[6] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(buffer.Length & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -588,11 +595,11 @@ namespace DiscImageChef.Devices
|
||||
if(sense) return true;
|
||||
|
||||
uint strctLength = (uint)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3] + 4);
|
||||
buffer = new byte[strctLength];
|
||||
cdb[6] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(buffer.Length & 0xFF);
|
||||
buffer = new byte[strctLength];
|
||||
cdb[6] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
||||
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[9] = (byte)(buffer.Length & 0xFF);
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -615,11 +622,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="cache">If set to <c>true</c> device can return cached data.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte partition,
|
||||
ushort firstAttribute, bool cache, uint timeout, out double duration)
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
byte partition,
|
||||
ushort firstAttribute, bool cache, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, partition, firstAttribute, cache,
|
||||
timeout, out duration);
|
||||
timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -632,8 +641,9 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="cache">If set to <c>true</c> device can return cached data.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
ushort firstAttribute, bool cache, uint timeout, out double duration)
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
ushort firstAttribute, bool cache, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, 0, firstAttribute, cache, timeout,
|
||||
out duration);
|
||||
@@ -649,11 +659,12 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="firstAttribute">First attribute identifier.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte partition,
|
||||
ushort firstAttribute, uint timeout, out double duration)
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
byte partition,
|
||||
ushort firstAttribute, uint timeout, out double duration)
|
||||
{
|
||||
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, partition, firstAttribute, false,
|
||||
timeout, out duration);
|
||||
timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -665,8 +676,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="firstAttribute">First attribute identifier.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
ushort firstAttribute, uint timeout, out double duration)
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
ushort firstAttribute, uint timeout, out double duration)
|
||||
{
|
||||
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, 0, firstAttribute, false, timeout,
|
||||
out duration);
|
||||
@@ -683,11 +694,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="firstAttribute">First attribute identifier.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte volume,
|
||||
byte partition, ushort firstAttribute, uint timeout, out double duration)
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
byte volume,
|
||||
byte partition, ushort firstAttribute, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, volume, partition, firstAttribute, false,
|
||||
timeout, out duration);
|
||||
timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -702,11 +715,13 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="cache">If set to <c>true</c> device can return cached data.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte volume,
|
||||
byte partition, ushort firstAttribute, bool cache, uint timeout, out double duration)
|
||||
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
||||
byte volume,
|
||||
byte partition, ushort firstAttribute, bool cache,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, volume, partition, firstAttribute, cache,
|
||||
timeout, out duration);
|
||||
timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -719,7 +734,7 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
/// <param name="pageFormat">Set if page is formatted.</param>
|
||||
public bool ModeSelect(byte[] buffer, out byte[] senseBuffer, bool pageFormat, bool savePages, uint timeout,
|
||||
public bool ModeSelect(byte[] buffer, out byte[] senseBuffer, bool pageFormat, bool savePages, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
@@ -727,11 +742,11 @@ namespace DiscImageChef.Devices
|
||||
// Prevent overflows
|
||||
if(buffer.Length > 255)
|
||||
{
|
||||
if(PlatformId != PlatformID.Win32NT && PlatformId != PlatformID.Win32S &&
|
||||
PlatformId != PlatformID.Win32Windows && PlatformId != PlatformID.WinCE &&
|
||||
if(PlatformId != PlatformID.Win32NT && PlatformId != PlatformID.Win32S &&
|
||||
PlatformId != PlatformID.Win32Windows && PlatformId != PlatformID.WinCE &&
|
||||
PlatformId != PlatformID.WindowsPhone && PlatformId != PlatformID.Xbox) LastError = 75;
|
||||
else LastError = 111;
|
||||
Error = true;
|
||||
else LastError = 111;
|
||||
Error = true;
|
||||
duration = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -740,7 +755,7 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ModeSelect;
|
||||
if(pageFormat) cdb[1] += 0x10;
|
||||
if(savePages) cdb[1] += 0x01;
|
||||
if(savePages) cdb[1] += 0x01;
|
||||
cdb[4] = (byte)buffer.Length;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration,
|
||||
@@ -762,7 +777,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="timeout">Timeout in seconds.</param>
|
||||
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
||||
/// <param name="pageFormat">Set if page is formatted.</param>
|
||||
public bool ModeSelect10(byte[] buffer, out byte[] senseBuffer, bool pageFormat, bool savePages, uint timeout,
|
||||
public bool ModeSelect10(byte[] buffer, out byte[] senseBuffer, bool pageFormat, bool savePages,
|
||||
uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
@@ -770,11 +786,11 @@ namespace DiscImageChef.Devices
|
||||
// Prevent overflows
|
||||
if(buffer.Length > 65535)
|
||||
{
|
||||
if(PlatformId != PlatformID.Win32NT && PlatformId != PlatformID.Win32S &&
|
||||
PlatformId != PlatformID.Win32Windows && PlatformId != PlatformID.WinCE &&
|
||||
if(PlatformId != PlatformID.Win32NT && PlatformId != PlatformID.Win32S &&
|
||||
PlatformId != PlatformID.Win32Windows && PlatformId != PlatformID.WinCE &&
|
||||
PlatformId != PlatformID.WindowsPhone && PlatformId != PlatformID.Xbox) LastError = 75;
|
||||
else LastError = 111;
|
||||
Error = true;
|
||||
else LastError = 111;
|
||||
Error = true;
|
||||
duration = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -783,7 +799,7 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ModeSelect10;
|
||||
if(pageFormat) cdb[1] += 0x10;
|
||||
if(savePages) cdb[1] += 0x01;
|
||||
if(savePages) cdb[1] += 0x01;
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) << 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
|
||||
|
||||
@@ -76,19 +76,19 @@ namespace DiscImageChef.Devices
|
||||
/// </param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool LoadUnload(out byte[] senseBuffer, bool immediate, bool load, bool retense, bool endOfTape,
|
||||
bool hold, uint timeout, out double duration)
|
||||
public bool LoadUnload(out byte[] senseBuffer, bool immediate, bool load, bool retense, bool endOfTape,
|
||||
bool hold, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.LoadUnload;
|
||||
if(immediate) cdb[1] = 0x01;
|
||||
if(load) cdb[4] += 0x01;
|
||||
if(retense) cdb[4] += 0x02;
|
||||
if(immediate) cdb[1] = 0x01;
|
||||
if(load) cdb[4] += 0x01;
|
||||
if(retense) cdb[4] += 0x02;
|
||||
if(endOfTape) cdb[4] += 0x04;
|
||||
if(hold) cdb[4] += 0x08;
|
||||
if(hold) cdb[4] += 0x08;
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
|
||||
out bool sense);
|
||||
@@ -163,20 +163,21 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="objectId">Object identifier.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Locate(out byte[] senseBuffer, bool immediate, bool blockType, bool changePartition, byte partition,
|
||||
uint objectId, uint timeout, out double duration)
|
||||
public bool Locate(out byte[] senseBuffer, bool immediate, bool blockType, bool changePartition,
|
||||
byte partition,
|
||||
uint objectId, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
byte[] cdb = new byte[10];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Locate;
|
||||
if(immediate) cdb[1] += 0x01;
|
||||
if(immediate) cdb[1] += 0x01;
|
||||
if(changePartition) cdb[1] += 0x02;
|
||||
if(blockType) cdb[1] += 0x04;
|
||||
if(blockType) cdb[1] += 0x04;
|
||||
cdb[3] = (byte)((objectId & 0xFF000000) >> 24);
|
||||
cdb[4] = (byte)((objectId & 0xFF0000) >> 16);
|
||||
cdb[5] = (byte)((objectId & 0xFF00) >> 8);
|
||||
cdb[4] = (byte)((objectId & 0xFF0000) >> 16);
|
||||
cdb[5] = (byte)((objectId & 0xFF00) >> 8);
|
||||
cdb[6] = (byte)(objectId & 0xFF);
|
||||
cdb[8] = partition;
|
||||
|
||||
@@ -243,7 +244,7 @@ namespace DiscImageChef.Devices
|
||||
out double duration)
|
||||
{
|
||||
return Locate16(out senseBuffer, immediate, true, SscLogicalIdTypes.ObjectId, false, partition, lba,
|
||||
timeout, out duration);
|
||||
timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -258,27 +259,28 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="identifier">Destination identifier.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Locate16(out byte[] senseBuffer, bool immediate, bool changePartition, SscLogicalIdTypes destType,
|
||||
bool bam, byte partition, ulong identifier, uint timeout, out double duration)
|
||||
public bool Locate16(out byte[] senseBuffer, bool immediate, bool changePartition, SscLogicalIdTypes destType,
|
||||
bool bam, byte partition, ulong identifier, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[16];
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] cdb = new byte[16];
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] idBytes = BitConverter.GetBytes(identifier);
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Locate16;
|
||||
cdb[1] = (byte)((byte)destType << 3);
|
||||
if(immediate) cdb[1] += 0x01;
|
||||
if(immediate) cdb[1] += 0x01;
|
||||
if(changePartition) cdb[1] += 0x02;
|
||||
if(bam) cdb[2] = 0x01;
|
||||
if(bam) cdb[2] = 0x01;
|
||||
cdb[3] = partition;
|
||||
|
||||
cdb[4] = idBytes[7];
|
||||
cdb[5] = idBytes[6];
|
||||
cdb[6] = idBytes[5];
|
||||
cdb[7] = idBytes[4];
|
||||
cdb[8] = idBytes[3];
|
||||
cdb[9] = idBytes[2];
|
||||
cdb[4] = idBytes[7];
|
||||
cdb[5] = idBytes[6];
|
||||
cdb[6] = idBytes[5];
|
||||
cdb[7] = idBytes[4];
|
||||
cdb[8] = idBytes[3];
|
||||
cdb[9] = idBytes[2];
|
||||
cdb[10] = idBytes[1];
|
||||
cdb[11] = idBytes[0];
|
||||
|
||||
@@ -315,8 +317,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Read6(out byte[] buffer, out byte[] senseBuffer, bool sili, uint transferLen, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
public bool Read6(out byte[] buffer, out byte[] senseBuffer, bool sili, uint transferLen, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return Read6(out buffer, out senseBuffer, sili, false, transferLen, blockSize, timeout, out duration);
|
||||
}
|
||||
@@ -338,8 +340,9 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Read6(out byte[] buffer, out byte[] senseBuffer, bool sili, bool fixedLen, uint transferLen,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
public bool Read6(out byte[] buffer, out byte[] senseBuffer, bool sili, bool fixedLen,
|
||||
uint transferLen,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
buffer = fixedLen ? new byte[blockSize * transferLen] : new byte[transferLen];
|
||||
byte[] cdb = new byte[6];
|
||||
@@ -347,9 +350,9 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read6;
|
||||
if(fixedLen) cdb[1] += 0x01;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
cdb[2] = (byte)((transferLen & 0xFF0000) >> 16);
|
||||
cdb[3] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[4] = (byte)(transferLen & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -372,8 +375,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, bool sili, ulong objectId, uint blocks,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, bool sili, ulong objectId, uint blocks,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
return Read16(out buffer, out senseBuffer, sili, false, 0, objectId, blocks, blockSize, timeout,
|
||||
out duration);
|
||||
@@ -391,8 +394,9 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, bool sili, byte partition, ulong objectId,
|
||||
uint blocks, uint blockSize, uint timeout, out double duration)
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, bool sili, byte partition,
|
||||
ulong objectId,
|
||||
uint blocks, uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
return Read16(out buffer, out senseBuffer, sili, false, partition, objectId, blocks, blockSize, timeout,
|
||||
out duration);
|
||||
@@ -408,8 +412,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, ulong objectId, uint blocks, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, ulong objectId, uint blocks, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return Read16(out buffer, out senseBuffer, false, true, 0, objectId, blocks, blockSize, timeout,
|
||||
out duration);
|
||||
@@ -426,8 +430,9 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, byte partition, ulong objectId, uint blocks,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, byte partition, ulong objectId,
|
||||
uint blocks,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
return Read16(out buffer, out senseBuffer, false, true, partition, objectId, blocks, blockSize, timeout,
|
||||
out duration);
|
||||
@@ -452,8 +457,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="objectSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, bool sili, bool fixedLen, byte partition,
|
||||
ulong objectId, uint transferLen, uint objectSize, uint timeout, out double duration)
|
||||
public bool Read16(out byte[] buffer, out byte[] senseBuffer, bool sili, bool fixedLen,
|
||||
byte partition,
|
||||
ulong objectId, uint transferLen, uint objectSize, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = fixedLen ? new byte[objectSize * transferLen] : new byte[transferLen];
|
||||
byte[] cdb = new byte[6];
|
||||
@@ -462,18 +469,18 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read16;
|
||||
if(fixedLen) cdb[1] += 0x01;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
cdb[3] = partition;
|
||||
cdb[4] = idBytes[7];
|
||||
cdb[5] = idBytes[6];
|
||||
cdb[6] = idBytes[5];
|
||||
cdb[7] = idBytes[4];
|
||||
cdb[8] = idBytes[3];
|
||||
cdb[9] = idBytes[2];
|
||||
if(sili) cdb[1] += 0x02;
|
||||
cdb[3] = partition;
|
||||
cdb[4] = idBytes[7];
|
||||
cdb[5] = idBytes[6];
|
||||
cdb[6] = idBytes[5];
|
||||
cdb[7] = idBytes[4];
|
||||
cdb[8] = idBytes[3];
|
||||
cdb[9] = idBytes[2];
|
||||
cdb[10] = idBytes[1];
|
||||
cdb[11] = idBytes[0];
|
||||
cdb[12] = (byte)((transferLen & 0xFF0000) >> 16);
|
||||
cdb[13] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[13] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[14] = (byte)(transferLen & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -543,12 +550,12 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="totalPosition">Requests current logical position.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadPosition(out byte[] buffer, out byte[] senseBuffer, bool vendorType, bool longForm,
|
||||
bool totalPosition, uint timeout, out double duration)
|
||||
public bool ReadPosition(out byte[] buffer, out byte[] senseBuffer, bool vendorType, bool longForm,
|
||||
bool totalPosition, uint timeout, out double duration)
|
||||
{
|
||||
byte responseForm = 0;
|
||||
if(vendorType) responseForm += 0x01;
|
||||
if(longForm) responseForm += 0x02;
|
||||
byte responseForm = 0;
|
||||
if(vendorType) responseForm += 0x01;
|
||||
if(longForm) responseForm += 0x02;
|
||||
if(totalPosition) responseForm += 0x04;
|
||||
|
||||
return ReadPosition(out buffer, out senseBuffer, (SscPositionForms)responseForm, timeout, out duration);
|
||||
@@ -631,8 +638,9 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadReverse6(out byte[] buffer, out byte[] senseBuffer, bool sili, uint transferLen, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
public bool ReadReverse6(out byte[] buffer, out byte[] senseBuffer, bool sili, uint transferLen,
|
||||
uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return ReadReverse6(out buffer, out senseBuffer, false, sili, false, transferLen, blockSize, timeout,
|
||||
out duration);
|
||||
@@ -656,19 +664,20 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadReverse6(out byte[] buffer, out byte[] senseBuffer, bool byteOrder, bool sili, bool fixedLen,
|
||||
uint transferLen, uint blockSize, uint timeout, out double duration)
|
||||
public bool ReadReverse6(out byte[] buffer, out byte[] senseBuffer, bool byteOrder, bool sili,
|
||||
bool fixedLen,
|
||||
uint transferLen, uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
buffer = fixedLen ? new byte[blockSize * transferLen] : new byte[transferLen];
|
||||
byte[] cdb = new byte[6];
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReadReverse;
|
||||
if(fixedLen) cdb[1] += 0x01;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
if(fixedLen) cdb[1] += 0x01;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
if(byteOrder) cdb[1] += 0x04;
|
||||
cdb[2] = (byte)((transferLen & 0xFF0000) >> 16);
|
||||
cdb[3] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[4] = (byte)(transferLen & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -691,11 +700,12 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, bool sili, ulong objectId, uint blocks,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, bool sili, ulong objectId,
|
||||
uint blocks,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
return ReadReverse16(out buffer, out senseBuffer, false, sili, false, 0, objectId, blocks, blockSize,
|
||||
timeout, out duration);
|
||||
timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -710,11 +720,12 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, bool sili, byte partition, ulong objectId,
|
||||
uint blocks, uint blockSize, uint timeout, out double duration)
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, bool sili, byte partition,
|
||||
ulong objectId,
|
||||
uint blocks, uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
return ReadReverse16(out buffer, out senseBuffer, false, sili, false, partition, objectId, blocks,
|
||||
blockSize, timeout, out duration);
|
||||
blockSize, timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -727,11 +738,11 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, ulong objectId, uint blocks,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, ulong objectId, uint blocks,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
return ReadReverse16(out buffer, out senseBuffer, false, false, true, 0, objectId, blocks, blockSize,
|
||||
timeout, out duration);
|
||||
timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -745,11 +756,11 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, byte partition, ulong objectId,
|
||||
uint blocks, uint blockSize, uint timeout, out double duration)
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, byte partition, ulong objectId,
|
||||
uint blocks, uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
return ReadReverse16(out buffer, out senseBuffer, false, false, true, partition, objectId, blocks,
|
||||
blockSize, timeout, out duration);
|
||||
blockSize, timeout, out duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -772,8 +783,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="objectSize">Object size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, bool byteOrder, bool sili, bool fixedLen,
|
||||
byte partition, ulong objectId, uint transferLen, uint objectSize, uint timeout,
|
||||
public bool ReadReverse16(out byte[] buffer, out byte[] senseBuffer, bool byteOrder, bool sili,
|
||||
bool fixedLen,
|
||||
byte partition, ulong objectId, uint transferLen, uint objectSize,
|
||||
uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = fixedLen ? new byte[objectSize * transferLen] : new byte[transferLen];
|
||||
@@ -782,20 +795,20 @@ namespace DiscImageChef.Devices
|
||||
byte[] idBytes = BitConverter.GetBytes(objectId);
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read16;
|
||||
if(fixedLen) cdb[1] += 0x01;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
if(fixedLen) cdb[1] += 0x01;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
if(byteOrder) cdb[1] += 0x04;
|
||||
cdb[3] = partition;
|
||||
cdb[4] = idBytes[7];
|
||||
cdb[5] = idBytes[6];
|
||||
cdb[6] = idBytes[5];
|
||||
cdb[7] = idBytes[4];
|
||||
cdb[8] = idBytes[3];
|
||||
cdb[9] = idBytes[2];
|
||||
cdb[3] = partition;
|
||||
cdb[4] = idBytes[7];
|
||||
cdb[5] = idBytes[6];
|
||||
cdb[6] = idBytes[5];
|
||||
cdb[7] = idBytes[4];
|
||||
cdb[8] = idBytes[3];
|
||||
cdb[9] = idBytes[2];
|
||||
cdb[10] = idBytes[1];
|
||||
cdb[11] = idBytes[0];
|
||||
cdb[12] = (byte)((transferLen & 0xFF0000) >> 16);
|
||||
cdb[13] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[13] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[14] = (byte)(transferLen & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -816,8 +829,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool RecoverBufferedData(out byte[] buffer, out byte[] senseBuffer, uint blocks, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
public bool RecoverBufferedData(out byte[] buffer, out byte[] senseBuffer, uint blocks, uint blockSize,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
return RecoverBufferedData(out buffer, out senseBuffer, false, true, blocks, blockSize, timeout,
|
||||
out duration);
|
||||
@@ -833,8 +846,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool RecoverBufferedData(out byte[] buffer, out byte[] senseBuffer, bool sili, uint transferLen,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
public bool RecoverBufferedData(out byte[] buffer, out byte[] senseBuffer, bool sili, uint transferLen,
|
||||
uint blockSize, uint timeout, out double duration)
|
||||
{
|
||||
return RecoverBufferedData(out buffer, out senseBuffer, sili, false, transferLen, blockSize, timeout,
|
||||
out duration);
|
||||
@@ -857,8 +870,10 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool RecoverBufferedData(out byte[] buffer, out byte[] senseBuffer, bool sili, bool fixedLen,
|
||||
uint transferLen, uint blockSize, uint timeout, out double duration)
|
||||
public bool RecoverBufferedData(out byte[] buffer, out byte[] senseBuffer, bool sili,
|
||||
bool fixedLen,
|
||||
uint transferLen, uint blockSize, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
buffer = fixedLen ? new byte[blockSize * transferLen] : new byte[transferLen];
|
||||
byte[] cdb = new byte[6];
|
||||
@@ -866,9 +881,9 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.RecoverBufferedData;
|
||||
if(fixedLen) cdb[1] += 0x01;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
if(sili) cdb[1] += 0x02;
|
||||
cdb[2] = (byte)((transferLen & 0xFF0000) >> 16);
|
||||
cdb[3] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((transferLen & 0xFF00) >> 8);
|
||||
cdb[4] = (byte)(transferLen & 0xFF);
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -915,8 +930,8 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="currentMedia">If set to <c>true</c> descriptors should apply to currently inserted media.</param>
|
||||
/// <param name="timeout">Timeout.</param>
|
||||
/// <param name="duration">Duration.</param>
|
||||
public bool ReportDensitySupport(out byte[] buffer, out byte[] senseBuffer, bool mediumType, bool currentMedia,
|
||||
uint timeout, out double duration)
|
||||
public bool ReportDensitySupport(out byte[] buffer, out byte[] senseBuffer, bool mediumType, bool currentMedia,
|
||||
uint timeout, out double duration)
|
||||
{
|
||||
buffer = new byte[256];
|
||||
byte[] cdb = new byte[10];
|
||||
@@ -924,7 +939,7 @@ namespace DiscImageChef.Devices
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.ReportDensitySupport;
|
||||
if(currentMedia) cdb[1] += 0x01;
|
||||
if(mediumType) cdb[1] += 0x02;
|
||||
if(mediumType) cdb[1] += 0x02;
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
|
||||
@@ -935,9 +950,9 @@ namespace DiscImageChef.Devices
|
||||
if(sense) return true;
|
||||
|
||||
ushort availableLength = (ushort)((buffer[0] << 8) + buffer[1] + 2);
|
||||
buffer = new byte[availableLength];
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
buffer = new byte[availableLength];
|
||||
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(buffer.Length & 0xFF);
|
||||
senseBuffer = new byte[32];
|
||||
|
||||
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
||||
@@ -970,7 +985,7 @@ namespace DiscImageChef.Devices
|
||||
public bool Rewind(out byte[] senseBuffer, bool immediate, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Rewind;
|
||||
@@ -996,7 +1011,7 @@ namespace DiscImageChef.Devices
|
||||
public bool TrackSelect(out byte[] senseBuffer, byte track, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.TrackSelect;
|
||||
@@ -1014,7 +1029,7 @@ namespace DiscImageChef.Devices
|
||||
public bool Space(out byte[] senseBuffer, SscSpaceCodes code, int count, uint timeout, out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] cdb = new byte[6];
|
||||
byte[] buffer = new byte[0];
|
||||
byte[] countB = BitConverter.GetBytes(count);
|
||||
|
||||
|
||||
@@ -81,20 +81,21 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="readLong">If set to <c>true</c> drive will return ECC bytes and disable error detection.</param>
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
public bool SyQuestRead6(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
byte transferLength, bool inhibitDma, bool readLong, uint timeout, out double duration)
|
||||
public bool SyQuestRead6(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
byte transferLength, bool inhibitDma, bool readLong, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[6];
|
||||
bool sense;
|
||||
bool sense;
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read6;
|
||||
cdb[1] = (byte)((lba & 0x1F0000) >> 16);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[2] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)(lba & 0xFF);
|
||||
cdb[4] = transferLength;
|
||||
if(inhibitDma) cdb[5] += 0x80;
|
||||
if(readLong) cdb[5] += 0x40;
|
||||
if(readLong) cdb[5] += 0x40;
|
||||
|
||||
if(!inhibitDma && !readLong)
|
||||
buffer = transferLength == 0 ? new byte[256 * blockSize] : new byte[transferLength * blockSize];
|
||||
@@ -161,23 +162,23 @@ namespace DiscImageChef.Devices
|
||||
/// <param name="readLong">If set to <c>true</c> drive will return ECC bytes and disable error detection.</param>
|
||||
/// <param name="blockSize">Block size in bytes.</param>
|
||||
/// <param name="transferLength">How many blocks to read.</param>
|
||||
public bool SyQuestRead10(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
ushort transferLength, bool inhibitDma, bool readLong, uint timeout,
|
||||
public bool SyQuestRead10(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize,
|
||||
ushort transferLength, bool inhibitDma, bool readLong, uint timeout,
|
||||
out double duration)
|
||||
{
|
||||
senseBuffer = new byte[32];
|
||||
byte[] cdb = new byte[10];
|
||||
bool sense;
|
||||
bool sense;
|
||||
|
||||
cdb[0] = (byte)ScsiCommands.Read10;
|
||||
cdb[2] = (byte)((lba & 0xFF000000) >> 24);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[3] = (byte)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (byte)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (byte)(lba & 0xFF);
|
||||
cdb[7] = (byte)((transferLength & 0xFF00) >> 8);
|
||||
cdb[8] = (byte)(transferLength & 0xFF);
|
||||
if(inhibitDma) cdb[9] += 0x80;
|
||||
if(readLong) cdb[9] += 0x40;
|
||||
if(readLong) cdb[9] += 0x40;
|
||||
|
||||
if(!inhibitDma && !readLong) buffer = new byte[transferLength * blockSize];
|
||||
else if(readLong)
|
||||
|
||||
@@ -39,9 +39,9 @@ namespace DiscImageChef.Devices
|
||||
{
|
||||
readonly ushort usbVendor;
|
||||
readonly ushort usbProduct;
|
||||
readonly ulong firewireGuid;
|
||||
readonly uint firewireModel;
|
||||
readonly uint firewireVendor;
|
||||
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.
|
||||
|
||||
@@ -640,7 +640,7 @@ namespace DiscImageChef.Devices
|
||||
/// Requests SPC-4 style error data
|
||||
/// </summary>
|
||||
RequestSenseDataExt = 0x0B,
|
||||
SanitizeCommands = 0xB4,
|
||||
SanitizeCommands = 0xB4,
|
||||
/// <summary>
|
||||
/// Executes a Security Protocol command that does not require a transfer of data
|
||||
/// </summary>
|
||||
@@ -2394,7 +2394,7 @@ namespace DiscImageChef.Devices
|
||||
/// Sets the spindle speed to be used while reading/writing data to a CD
|
||||
/// </summary>
|
||||
SetCdSpeed = 0xDA,
|
||||
WriteCdp = 0xE3,
|
||||
WriteCdp = 0xE3,
|
||||
#endregion
|
||||
|
||||
#region ATA Command Pass-Through
|
||||
@@ -2841,7 +2841,7 @@ namespace DiscImageChef.Devices
|
||||
/// <summary>
|
||||
/// Drive shall return only the Feature Header with the chosen Feature Descriptor
|
||||
/// </summary>
|
||||
Single = 0x02,
|
||||
Single = 0x02,
|
||||
Reserved = 0x03
|
||||
}
|
||||
|
||||
@@ -3505,8 +3505,8 @@ namespace DiscImageChef.Devices
|
||||
/// The host sends the bus testing data pattern to a device (ADTC, R1)
|
||||
/// </summary>
|
||||
BusTestWrite = 19,
|
||||
SpiReadOcr = 58,
|
||||
SpicrcOnOff = 59,
|
||||
SpiReadOcr = 58,
|
||||
SpicrcOnOff = 59,
|
||||
#endregion Class 1 MMC Commands (Basic and read-stream)
|
||||
|
||||
#region Class 2 MMC Commands (Block-oriented read)
|
||||
@@ -3756,9 +3756,9 @@ namespace DiscImageChef.Devices
|
||||
ResponseSpiB4 = 1 << 9,
|
||||
ResponseSpiBusy = 1 << 10,
|
||||
ResponseNone = 0,
|
||||
ResponseR1 = ResponsePresent | ResponseCrc | ResponseOpcode,
|
||||
ResponseR1 = ResponsePresent | ResponseCrc | ResponseOpcode,
|
||||
ResponseR1B = ResponsePresent | ResponseCrc | ResponseOpcode | ResponseBusy,
|
||||
ResponseR2 = ResponsePresent | Response136 | ResponseCrc,
|
||||
ResponseR2 = ResponsePresent | Response136 | ResponseCrc,
|
||||
ResponseR3 = ResponsePresent,
|
||||
ResponseR4 = ResponsePresent,
|
||||
ResponseR5 = ResponsePresent | ResponseCrc | ResponseOpcode,
|
||||
@@ -3916,7 +3916,7 @@ namespace DiscImageChef.Devices
|
||||
DisableReleaseInterrupt = 0xDD,
|
||||
/// <summary>Disable SERVICE interrupt</summary>
|
||||
DisableServiceInterrupt = 0xDE,
|
||||
VendorSpecific = 0xE0
|
||||
VendorSpecific = 0xE0
|
||||
}
|
||||
|
||||
public enum KreonLockStates : byte
|
||||
|
||||
@@ -60,12 +60,13 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI
|
||||
/// sense
|
||||
/// </param>
|
||||
internal static int SendScsiCommand64(IntPtr dev, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer,
|
||||
uint timeout, CcbFlags direction, out double duration, out bool sense)
|
||||
internal static int SendScsiCommand64(IntPtr dev, byte[] cdb, ref byte[] buffer,
|
||||
out byte[] senseBuffer,
|
||||
uint timeout, CcbFlags direction, out double duration, out bool sense)
|
||||
{
|
||||
senseBuffer = null;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
|
||||
if(buffer == null) return -1;
|
||||
|
||||
@@ -79,19 +80,19 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
}
|
||||
|
||||
CcbScsiio64 csio = (CcbScsiio64)Marshal.PtrToStructure(ccbPtr, typeof(CcbScsiio64));
|
||||
csio.ccb_h.func_code = XptOpcode.XptScsiIo;
|
||||
csio.ccb_h.flags = direction;
|
||||
csio.ccb_h.xflags = 0;
|
||||
csio.ccb_h.func_code = XptOpcode.XptScsiIo;
|
||||
csio.ccb_h.flags = direction;
|
||||
csio.ccb_h.xflags = 0;
|
||||
csio.ccb_h.retry_count = 1;
|
||||
csio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
csio.ccb_h.timeout = timeout;
|
||||
csio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
csio.dxfer_len = (uint)buffer.Length;
|
||||
csio.sense_len = 32;
|
||||
csio.cdb_len = (byte)cdb.Length;
|
||||
csio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
csio.ccb_h.timeout = timeout;
|
||||
csio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
csio.dxfer_len = (uint)buffer.Length;
|
||||
csio.sense_len = 32;
|
||||
csio.cdb_len = (byte)cdb.Length;
|
||||
// TODO: Create enum?
|
||||
csio.tag_action = 0x20;
|
||||
csio.cdb_bytes = new byte[CAM_MAX_CDBLEN];
|
||||
csio.cdb_bytes = new byte[CAM_MAX_CDBLEN];
|
||||
if(cdb.Length <= CAM_MAX_CDBLEN) Array.Copy(cdb, 0, csio.cdb_bytes, 0, cdb.Length);
|
||||
else
|
||||
{
|
||||
@@ -100,14 +101,15 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
Array.Copy(cdbPtrBytes, 0, csio.cdb_bytes, 0, IntPtr.Size);
|
||||
csio.ccb_h.flags |= CcbFlags.CamCdbPointer;
|
||||
}
|
||||
|
||||
csio.ccb_h.flags |= CcbFlags.CamDevQfrzdis;
|
||||
|
||||
Marshal.Copy(buffer, 0, csio.data_ptr, buffer.Length);
|
||||
Marshal.StructureToPtr(csio, ccbPtr, false);
|
||||
|
||||
DateTime start = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
|
||||
if(error < 0) error = Marshal.GetLastWin32Error();
|
||||
|
||||
@@ -123,22 +125,22 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
|
||||
if((csio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamScsiStatusError)
|
||||
{
|
||||
sense = true;
|
||||
senseBuffer = new byte[1];
|
||||
sense = true;
|
||||
senseBuffer = new byte[1];
|
||||
senseBuffer[0] = csio.scsi_status;
|
||||
}
|
||||
|
||||
if((csio.ccb_h.status & CamStatus.CamAutosnsValid) != 0)
|
||||
if(csio.sense_len - csio.sense_resid > 0)
|
||||
{
|
||||
sense = (csio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamScsiStatusError;
|
||||
senseBuffer = new byte[csio.sense_len - csio.sense_resid];
|
||||
sense = (csio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamScsiStatusError;
|
||||
senseBuffer = new byte[csio.sense_len - csio.sense_resid];
|
||||
senseBuffer[0] = csio.sense_data.error_code;
|
||||
Array.Copy(csio.sense_data.sense_buf, 0, senseBuffer, 1, senseBuffer.Length - 1);
|
||||
}
|
||||
|
||||
buffer = new byte[csio.dxfer_len];
|
||||
cdb = new byte[csio.cdb_len];
|
||||
cdb = new byte[csio.cdb_len];
|
||||
|
||||
Marshal.Copy(csio.data_ptr, buffer, 0, buffer.Length);
|
||||
if(csio.ccb_h.flags.HasFlag(CcbFlags.CamCdbPointer))
|
||||
@@ -168,12 +170,13 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI
|
||||
/// sense
|
||||
/// </param>
|
||||
internal static int SendScsiCommand(IntPtr dev, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer,
|
||||
uint timeout, CcbFlags direction, out double duration, out bool sense)
|
||||
internal static int SendScsiCommand(IntPtr dev, byte[] cdb, ref byte[] buffer,
|
||||
out byte[] senseBuffer,
|
||||
uint timeout, CcbFlags direction, out double duration, out bool sense)
|
||||
{
|
||||
senseBuffer = null;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
|
||||
if(buffer == null) return -1;
|
||||
|
||||
@@ -187,19 +190,19 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
}
|
||||
|
||||
CcbScsiio csio = (CcbScsiio)Marshal.PtrToStructure(ccbPtr, typeof(CcbScsiio));
|
||||
csio.ccb_h.func_code = XptOpcode.XptScsiIo;
|
||||
csio.ccb_h.flags = direction;
|
||||
csio.ccb_h.xflags = 0;
|
||||
csio.ccb_h.func_code = XptOpcode.XptScsiIo;
|
||||
csio.ccb_h.flags = direction;
|
||||
csio.ccb_h.xflags = 0;
|
||||
csio.ccb_h.retry_count = 1;
|
||||
csio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
csio.ccb_h.timeout = timeout;
|
||||
csio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
csio.dxfer_len = (uint)buffer.Length;
|
||||
csio.sense_len = 32;
|
||||
csio.cdb_len = (byte)cdb.Length;
|
||||
csio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
csio.ccb_h.timeout = timeout;
|
||||
csio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
csio.dxfer_len = (uint)buffer.Length;
|
||||
csio.sense_len = 32;
|
||||
csio.cdb_len = (byte)cdb.Length;
|
||||
// TODO: Create enum?
|
||||
csio.tag_action = 0x20;
|
||||
csio.cdb_bytes = new byte[CAM_MAX_CDBLEN];
|
||||
csio.cdb_bytes = new byte[CAM_MAX_CDBLEN];
|
||||
if(cdb.Length <= CAM_MAX_CDBLEN) Array.Copy(cdb, 0, csio.cdb_bytes, 0, cdb.Length);
|
||||
else
|
||||
{
|
||||
@@ -208,14 +211,15 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
Array.Copy(cdbPtrBytes, 0, csio.cdb_bytes, 0, IntPtr.Size);
|
||||
csio.ccb_h.flags |= CcbFlags.CamCdbPointer;
|
||||
}
|
||||
|
||||
csio.ccb_h.flags |= CcbFlags.CamDevQfrzdis;
|
||||
|
||||
Marshal.Copy(buffer, 0, csio.data_ptr, buffer.Length);
|
||||
Marshal.StructureToPtr(csio, ccbPtr, false);
|
||||
|
||||
DateTime start = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
|
||||
if(error < 0) error = Marshal.GetLastWin32Error();
|
||||
|
||||
@@ -231,22 +235,22 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
|
||||
if((csio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamScsiStatusError)
|
||||
{
|
||||
sense = true;
|
||||
senseBuffer = new byte[1];
|
||||
sense = true;
|
||||
senseBuffer = new byte[1];
|
||||
senseBuffer[0] = csio.scsi_status;
|
||||
}
|
||||
|
||||
if((csio.ccb_h.status & CamStatus.CamAutosnsValid) != 0)
|
||||
if(csio.sense_len - csio.sense_resid > 0)
|
||||
{
|
||||
sense = (csio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamScsiStatusError;
|
||||
senseBuffer = new byte[csio.sense_len - csio.sense_resid];
|
||||
sense = (csio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamScsiStatusError;
|
||||
senseBuffer = new byte[csio.sense_len - csio.sense_resid];
|
||||
senseBuffer[0] = csio.sense_data.error_code;
|
||||
Array.Copy(csio.sense_data.sense_buf, 0, senseBuffer, 1, senseBuffer.Length - 1);
|
||||
}
|
||||
|
||||
buffer = new byte[csio.dxfer_len];
|
||||
cdb = new byte[csio.cdb_len];
|
||||
cdb = new byte[csio.cdb_len];
|
||||
|
||||
Marshal.Copy(csio.data_ptr, buffer, 0, buffer.Length);
|
||||
if(csio.ccb_h.flags.HasFlag(CcbFlags.CamCdbPointer))
|
||||
@@ -296,12 +300,13 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <param name="registers">Registers to send to drive</param>
|
||||
/// <param name="errorRegisters">Registers returned by drive</param>
|
||||
/// <param name="protocol">ATA protocol to use</param>
|
||||
internal static int SendAtaCommand(IntPtr dev, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(IntPtr dev, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
errorRegisters = new AtaErrorRegistersChs();
|
||||
|
||||
if(buffer == null) return -1;
|
||||
@@ -309,16 +314,16 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
IntPtr ccbPtr = cam_getccb(dev);
|
||||
|
||||
CcbAtaio ataio = (CcbAtaio)Marshal.PtrToStructure(ccbPtr, typeof(CcbAtaio));
|
||||
ataio.ccb_h.func_code = XptOpcode.XptAtaIo;
|
||||
ataio.ccb_h.flags = AtaProtocolToCamFlags(protocol);
|
||||
ataio.ccb_h.xflags = 0;
|
||||
ataio.ccb_h.retry_count = 1;
|
||||
ataio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
ataio.ccb_h.timeout = timeout;
|
||||
ataio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
ataio.dxfer_len = (uint)buffer.Length;
|
||||
ataio.ccb_h.flags |= CcbFlags.CamDevQfrzdis;
|
||||
ataio.cmd.flags = CamAtaIoFlags.NeedResult;
|
||||
ataio.ccb_h.func_code = XptOpcode.XptAtaIo;
|
||||
ataio.ccb_h.flags = AtaProtocolToCamFlags(protocol);
|
||||
ataio.ccb_h.xflags = 0;
|
||||
ataio.ccb_h.retry_count = 1;
|
||||
ataio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
ataio.ccb_h.timeout = timeout;
|
||||
ataio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
ataio.dxfer_len = (uint)buffer.Length;
|
||||
ataio.ccb_h.flags |= CcbFlags.CamDevQfrzdis;
|
||||
ataio.cmd.flags = CamAtaIoFlags.NeedResult;
|
||||
switch(protocol)
|
||||
{
|
||||
case AtaProtocol.Dma:
|
||||
@@ -332,20 +337,20 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
break;
|
||||
}
|
||||
|
||||
ataio.cmd.command = registers.Command;
|
||||
ataio.cmd.lba_high = registers.CylinderHigh;
|
||||
ataio.cmd.lba_mid = registers.CylinderLow;
|
||||
ataio.cmd.device = (byte)(0x40 | registers.DeviceHead);
|
||||
ataio.cmd.features = registers.Feature;
|
||||
ataio.cmd.command = registers.Command;
|
||||
ataio.cmd.lba_high = registers.CylinderHigh;
|
||||
ataio.cmd.lba_mid = registers.CylinderLow;
|
||||
ataio.cmd.device = (byte)(0x40 | registers.DeviceHead);
|
||||
ataio.cmd.features = registers.Feature;
|
||||
ataio.cmd.sector_count = registers.SectorCount;
|
||||
ataio.cmd.lba_low = registers.Sector;
|
||||
ataio.cmd.lba_low = registers.Sector;
|
||||
|
||||
Marshal.Copy(buffer, 0, ataio.data_ptr, buffer.Length);
|
||||
Marshal.StructureToPtr(ataio, ccbPtr, false);
|
||||
|
||||
DateTime start = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
|
||||
if(error < 0) error = Marshal.GetLastWin32Error();
|
||||
|
||||
@@ -362,12 +367,12 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
if((ataio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamAtaStatusError) sense = true;
|
||||
|
||||
errorRegisters.CylinderHigh = ataio.res.lba_high;
|
||||
errorRegisters.CylinderLow = ataio.res.lba_mid;
|
||||
errorRegisters.DeviceHead = ataio.res.device;
|
||||
errorRegisters.Error = ataio.res.error;
|
||||
errorRegisters.Sector = ataio.res.lba_low;
|
||||
errorRegisters.SectorCount = ataio.res.sector_count;
|
||||
errorRegisters.Status = ataio.res.status;
|
||||
errorRegisters.CylinderLow = ataio.res.lba_mid;
|
||||
errorRegisters.DeviceHead = ataio.res.device;
|
||||
errorRegisters.Error = ataio.res.error;
|
||||
errorRegisters.Sector = ataio.res.lba_low;
|
||||
errorRegisters.SectorCount = ataio.res.sector_count;
|
||||
errorRegisters.Status = ataio.res.status;
|
||||
|
||||
buffer = new byte[ataio.dxfer_len];
|
||||
|
||||
@@ -394,12 +399,13 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <param name="registers">Registers to send to drive</param>
|
||||
/// <param name="errorRegisters">Registers returned by drive</param>
|
||||
/// <param name="protocol">ATA protocol to use</param>
|
||||
internal static int SendAtaCommand(IntPtr dev, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(IntPtr dev, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
errorRegisters = new AtaErrorRegistersLba28();
|
||||
|
||||
if(buffer == null) return -1;
|
||||
@@ -407,16 +413,16 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
IntPtr ccbPtr = cam_getccb(dev);
|
||||
|
||||
CcbAtaio ataio = (CcbAtaio)Marshal.PtrToStructure(ccbPtr, typeof(CcbAtaio));
|
||||
ataio.ccb_h.func_code = XptOpcode.XptAtaIo;
|
||||
ataio.ccb_h.flags = AtaProtocolToCamFlags(protocol);
|
||||
ataio.ccb_h.xflags = 0;
|
||||
ataio.ccb_h.retry_count = 1;
|
||||
ataio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
ataio.ccb_h.timeout = timeout;
|
||||
ataio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
ataio.dxfer_len = (uint)buffer.Length;
|
||||
ataio.ccb_h.flags |= CcbFlags.CamDevQfrzdis;
|
||||
ataio.cmd.flags = CamAtaIoFlags.NeedResult;
|
||||
ataio.ccb_h.func_code = XptOpcode.XptAtaIo;
|
||||
ataio.ccb_h.flags = AtaProtocolToCamFlags(protocol);
|
||||
ataio.ccb_h.xflags = 0;
|
||||
ataio.ccb_h.retry_count = 1;
|
||||
ataio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
ataio.ccb_h.timeout = timeout;
|
||||
ataio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
ataio.dxfer_len = (uint)buffer.Length;
|
||||
ataio.ccb_h.flags |= CcbFlags.CamDevQfrzdis;
|
||||
ataio.cmd.flags = CamAtaIoFlags.NeedResult;
|
||||
switch(protocol)
|
||||
{
|
||||
case AtaProtocol.Dma:
|
||||
@@ -430,20 +436,20 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
break;
|
||||
}
|
||||
|
||||
ataio.cmd.command = registers.Command;
|
||||
ataio.cmd.lba_high = registers.LbaHigh;
|
||||
ataio.cmd.lba_mid = registers.LbaMid;
|
||||
ataio.cmd.device = (byte)(0x40 | registers.DeviceHead);
|
||||
ataio.cmd.features = registers.Feature;
|
||||
ataio.cmd.command = registers.Command;
|
||||
ataio.cmd.lba_high = registers.LbaHigh;
|
||||
ataio.cmd.lba_mid = registers.LbaMid;
|
||||
ataio.cmd.device = (byte)(0x40 | registers.DeviceHead);
|
||||
ataio.cmd.features = registers.Feature;
|
||||
ataio.cmd.sector_count = registers.SectorCount;
|
||||
ataio.cmd.lba_low = registers.LbaLow;
|
||||
ataio.cmd.lba_low = registers.LbaLow;
|
||||
|
||||
Marshal.Copy(buffer, 0, ataio.data_ptr, buffer.Length);
|
||||
Marshal.StructureToPtr(ataio, ccbPtr, false);
|
||||
|
||||
DateTime start = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
|
||||
if(error < 0) error = Marshal.GetLastWin32Error();
|
||||
|
||||
@@ -459,13 +465,13 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
|
||||
if((ataio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamAtaStatusError) sense = true;
|
||||
|
||||
errorRegisters.LbaHigh = ataio.res.lba_high;
|
||||
errorRegisters.LbaMid = ataio.res.lba_mid;
|
||||
errorRegisters.DeviceHead = ataio.res.device;
|
||||
errorRegisters.Error = ataio.res.error;
|
||||
errorRegisters.LbaLow = ataio.res.lba_low;
|
||||
errorRegisters.LbaHigh = ataio.res.lba_high;
|
||||
errorRegisters.LbaMid = ataio.res.lba_mid;
|
||||
errorRegisters.DeviceHead = ataio.res.device;
|
||||
errorRegisters.Error = ataio.res.error;
|
||||
errorRegisters.LbaLow = ataio.res.lba_low;
|
||||
errorRegisters.SectorCount = ataio.res.sector_count;
|
||||
errorRegisters.Status = ataio.res.status;
|
||||
errorRegisters.Status = ataio.res.status;
|
||||
|
||||
buffer = new byte[ataio.dxfer_len];
|
||||
|
||||
@@ -492,12 +498,13 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <param name="registers">Registers to send to drive</param>
|
||||
/// <param name="errorRegisters">Registers returned by drive</param>
|
||||
/// <param name="protocol">ATA protocol to use</param>
|
||||
internal static int SendAtaCommand(IntPtr dev, AtaRegistersLba48 registers,
|
||||
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(IntPtr dev, AtaRegistersLba48 registers,
|
||||
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
errorRegisters = new AtaErrorRegistersLba48();
|
||||
|
||||
// 48-bit ATA CAM commands can crash FreeBSD < 9.2-RELEASE
|
||||
@@ -509,16 +516,16 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
IntPtr ccbPtr = cam_getccb(dev);
|
||||
|
||||
CcbAtaio ataio = (CcbAtaio)Marshal.PtrToStructure(ccbPtr, typeof(CcbAtaio));
|
||||
ataio.ccb_h.func_code = XptOpcode.XptAtaIo;
|
||||
ataio.ccb_h.flags = AtaProtocolToCamFlags(protocol);
|
||||
ataio.ccb_h.xflags = 0;
|
||||
ataio.ccb_h.retry_count = 1;
|
||||
ataio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
ataio.ccb_h.timeout = timeout;
|
||||
ataio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
ataio.dxfer_len = (uint)buffer.Length;
|
||||
ataio.ccb_h.flags |= CcbFlags.CamDevQfrzdis;
|
||||
ataio.cmd.flags = CamAtaIoFlags.NeedResult | CamAtaIoFlags.ExtendedCommand;
|
||||
ataio.ccb_h.func_code = XptOpcode.XptAtaIo;
|
||||
ataio.ccb_h.flags = AtaProtocolToCamFlags(protocol);
|
||||
ataio.ccb_h.xflags = 0;
|
||||
ataio.ccb_h.retry_count = 1;
|
||||
ataio.ccb_h.cbfcnp = IntPtr.Zero;
|
||||
ataio.ccb_h.timeout = timeout;
|
||||
ataio.data_ptr = Marshal.AllocHGlobal(buffer.Length);
|
||||
ataio.dxfer_len = (uint)buffer.Length;
|
||||
ataio.ccb_h.flags |= CcbFlags.CamDevQfrzdis;
|
||||
ataio.cmd.flags = CamAtaIoFlags.NeedResult | CamAtaIoFlags.ExtendedCommand;
|
||||
switch(protocol)
|
||||
{
|
||||
case AtaProtocol.Dma:
|
||||
@@ -532,25 +539,25 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
break;
|
||||
}
|
||||
|
||||
ataio.cmd.lba_high_exp = (byte)((registers.LbaHigh & 0xFF00) >> 8);
|
||||
ataio.cmd.lba_mid_exp = (byte)((registers.LbaMid & 0xFF00) >> 8);
|
||||
ataio.cmd.features_exp = (byte)((registers.Feature & 0xFF00) >> 8);
|
||||
ataio.cmd.lba_high_exp = (byte)((registers.LbaHigh & 0xFF00) >> 8);
|
||||
ataio.cmd.lba_mid_exp = (byte)((registers.LbaMid & 0xFF00) >> 8);
|
||||
ataio.cmd.features_exp = (byte)((registers.Feature & 0xFF00) >> 8);
|
||||
ataio.cmd.sector_count_exp = (byte)((registers.SectorCount & 0xFF00) >> 8);
|
||||
ataio.cmd.lba_low_exp = (byte)((registers.LbaLow & 0xFF00) >> 8);
|
||||
ataio.cmd.lba_high = (byte)(registers.LbaHigh & 0xFF);
|
||||
ataio.cmd.lba_mid = (byte)(registers.LbaMid & 0xFF);
|
||||
ataio.cmd.features = (byte)(registers.Feature & 0xFF);
|
||||
ataio.cmd.sector_count = (byte)(registers.SectorCount & 0xFF);
|
||||
ataio.cmd.lba_low = (byte)(registers.LbaLow & 0xFF);
|
||||
ataio.cmd.command = registers.Command;
|
||||
ataio.cmd.device = (byte)(0x40 | registers.DeviceHead);
|
||||
ataio.cmd.lba_low_exp = (byte)((registers.LbaLow & 0xFF00) >> 8);
|
||||
ataio.cmd.lba_high = (byte)(registers.LbaHigh & 0xFF);
|
||||
ataio.cmd.lba_mid = (byte)(registers.LbaMid & 0xFF);
|
||||
ataio.cmd.features = (byte)(registers.Feature & 0xFF);
|
||||
ataio.cmd.sector_count = (byte)(registers.SectorCount & 0xFF);
|
||||
ataio.cmd.lba_low = (byte)(registers.LbaLow & 0xFF);
|
||||
ataio.cmd.command = registers.Command;
|
||||
ataio.cmd.device = (byte)(0x40 | registers.DeviceHead);
|
||||
|
||||
Marshal.Copy(buffer, 0, ataio.data_ptr, buffer.Length);
|
||||
Marshal.StructureToPtr(ataio, ccbPtr, false);
|
||||
|
||||
DateTime start = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
int error = cam_send_ccb(dev, ccbPtr);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
|
||||
if(error < 0) error = Marshal.GetLastWin32Error();
|
||||
|
||||
@@ -567,12 +574,12 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
if((ataio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamAtaStatusError) sense = true;
|
||||
|
||||
errorRegisters.SectorCount = (ushort)((ataio.res.sector_count_exp << 8) + ataio.res.sector_count);
|
||||
errorRegisters.LbaLow = (ushort)((ataio.res.lba_low_exp << 8) + ataio.res.lba_low);
|
||||
errorRegisters.LbaMid = (ushort)((ataio.res.lba_mid_exp << 8) + ataio.res.lba_mid);
|
||||
errorRegisters.LbaHigh = (ushort)((ataio.res.lba_high_exp << 8) + ataio.res.lba_high);
|
||||
errorRegisters.DeviceHead = ataio.res.device;
|
||||
errorRegisters.Error = ataio.res.error;
|
||||
errorRegisters.Status = ataio.res.status;
|
||||
errorRegisters.LbaLow = (ushort)((ataio.res.lba_low_exp << 8) + ataio.res.lba_low);
|
||||
errorRegisters.LbaMid = (ushort)((ataio.res.lba_mid_exp << 8) + ataio.res.lba_mid);
|
||||
errorRegisters.LbaHigh = (ushort)((ataio.res.lba_high_exp << 8) + ataio.res.lba_high);
|
||||
errorRegisters.DeviceHead = ataio.res.device;
|
||||
errorRegisters.Error = ataio.res.error;
|
||||
errorRegisters.Status = ataio.res.status;
|
||||
|
||||
buffer = new byte[ataio.dxfer_len];
|
||||
|
||||
|
||||
@@ -269,34 +269,34 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[Flags]
|
||||
enum PeriphPatternFlags
|
||||
{
|
||||
PeriphMatchNone = 0x000,
|
||||
PeriphMatchPath = 0x001,
|
||||
PeriphMatchNone = 0x000,
|
||||
PeriphMatchPath = 0x001,
|
||||
PeriphMatchTarget = 0x002,
|
||||
PeriphMatchLun = 0x004,
|
||||
PeriphMatchName = 0x008,
|
||||
PeriphMatchUnit = 0x010
|
||||
PeriphMatchLun = 0x004,
|
||||
PeriphMatchName = 0x008,
|
||||
PeriphMatchUnit = 0x010
|
||||
// PERIPH_MATCH_ANY = 0x01f
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DevPatternFlags
|
||||
{
|
||||
DevMatchNone = 0x000,
|
||||
DevMatchPath = 0x001,
|
||||
DevMatchTarget = 0x002,
|
||||
DevMatchLun = 0x004,
|
||||
DevMatchNone = 0x000,
|
||||
DevMatchPath = 0x001,
|
||||
DevMatchTarget = 0x002,
|
||||
DevMatchLun = 0x004,
|
||||
DevMatchInquiry = 0x008,
|
||||
DevMatchDevid = 0x010
|
||||
DevMatchDevid = 0x010
|
||||
// DEV_MATCH_ANY = 0x00f
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum BusPatternFlags
|
||||
{
|
||||
BusMatchNone = 0x000,
|
||||
BusMatchPath = 0x001,
|
||||
BusMatchName = 0x002,
|
||||
BusMatchUnit = 0x004,
|
||||
BusMatchNone = 0x000,
|
||||
BusMatchPath = 0x001,
|
||||
BusMatchName = 0x002,
|
||||
BusMatchUnit = 0x004,
|
||||
BusMatchBusId = 0x008
|
||||
// BUS_MATCH_ANY = 0x00f
|
||||
}
|
||||
@@ -304,7 +304,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[Flags]
|
||||
enum DevResultFlags
|
||||
{
|
||||
DevResultNoflag = 0x00,
|
||||
DevResultNoflag = 0x00,
|
||||
DevResultUnconfigured = 0x01
|
||||
}
|
||||
|
||||
@@ -353,32 +353,32 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
enum MmcCardFeatures
|
||||
{
|
||||
CardFeatureMemory = 0x1,
|
||||
CardFeatureSdhc = 0x1 << 1,
|
||||
CardFeatureSdio = 0x1 << 2,
|
||||
CardFeatureSd20 = 0x1 << 3,
|
||||
CardFeatureMmc = 0x1 << 4,
|
||||
CardFeature18V = 0x1 << 5
|
||||
CardFeatureSdhc = 0x1 << 1,
|
||||
CardFeatureSdio = 0x1 << 2,
|
||||
CardFeatureSd20 = 0x1 << 3,
|
||||
CardFeatureMmc = 0x1 << 4,
|
||||
CardFeature18V = 0x1 << 5
|
||||
}
|
||||
|
||||
enum CamGenerations : uint
|
||||
{
|
||||
CamBusGeneration = 0x00,
|
||||
CamBusGeneration = 0x00,
|
||||
CamTargetGeneration = 0x01,
|
||||
CamDevGeneration = 0x02,
|
||||
CamDevGeneration = 0x02,
|
||||
CamPeriphGeneration = 0x03
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DevPosType
|
||||
{
|
||||
CamDevPosNone = 0x000,
|
||||
CamDevPosBus = 0x001,
|
||||
CamDevPosNone = 0x000,
|
||||
CamDevPosBus = 0x001,
|
||||
CamDevPosTarget = 0x002,
|
||||
CamDevPosDevice = 0x004,
|
||||
CamDevPosPeriph = 0x008,
|
||||
CamDevPosPdptr = 0x010,
|
||||
CamDevPosPdptr = 0x010,
|
||||
// CAM_DEV_POS_TYPEMASK = 0xf00,
|
||||
CamDevPosEdt = 0x100,
|
||||
CamDevPosEdt = 0x100,
|
||||
CamDevPosPdrv = 0x200
|
||||
}
|
||||
|
||||
|
||||
@@ -49,14 +49,14 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <returns>List of devices</returns>
|
||||
internal static DeviceInfo[] GetList()
|
||||
{
|
||||
string[] passDevices = Directory.GetFiles("/dev/", "pass*", SearchOption.TopDirectoryOnly);
|
||||
string[] passDevices = Directory.GetFiles("/dev/", "pass*", SearchOption.TopDirectoryOnly);
|
||||
List<DeviceInfo> listDevices = new List<DeviceInfo>();
|
||||
|
||||
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));
|
||||
IntPtr dev = cam_open_device(passDevice, FileFlags.ReadWrite);
|
||||
CamDevice camDevice = (CamDevice)Marshal.PtrToStructure(dev, typeof(CamDevice));
|
||||
|
||||
IntPtr ccbPtr = cam_getccb(dev);
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
for(int aIndex = 0; aIndex < 512; aIndex += 2)
|
||||
{
|
||||
atadTneid[aIndex] = cgd.ident_data[aIndex + 1];
|
||||
atadTneid[aIndex + 1] = cgd.ident_data[aIndex];
|
||||
atadTneid[aIndex + 1] = cgd.ident_data[aIndex];
|
||||
}
|
||||
|
||||
Identify.IdentifyDevice? idt = Identify.Decode(atadTneid);
|
||||
@@ -110,18 +110,19 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
if(separated.Length == 1)
|
||||
{
|
||||
deviceInfo.Vendor = "ATA";
|
||||
deviceInfo.Model = separated[0];
|
||||
deviceInfo.Model = separated[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceInfo.Vendor = separated[0];
|
||||
deviceInfo.Model = separated[separated.Length - 1];
|
||||
deviceInfo.Model = separated[separated.Length - 1];
|
||||
}
|
||||
|
||||
deviceInfo.Serial = idt.Value.SerialNumber;
|
||||
deviceInfo.Bus = simName == "ahcich" ? "SATA" : "ATA";
|
||||
deviceInfo.Serial = idt.Value.SerialNumber;
|
||||
deviceInfo.Bus = simName == "ahcich" ? "SATA" : "ATA";
|
||||
deviceInfo.Supported = simName != "ata";
|
||||
}
|
||||
|
||||
if(cgd.protocol == CamProto.ProtoAtapi) goto case CamProto.ProtoScsi;
|
||||
break;
|
||||
}
|
||||
@@ -130,20 +131,21 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
Inquiry.SCSIInquiry? inq = Inquiry.Decode(cgd.inq_data);
|
||||
if(inq.HasValue)
|
||||
{
|
||||
deviceInfo.Vendor = StringHandlers.CToString(inq.Value.VendorIdentification).Trim();
|
||||
deviceInfo.Model = StringHandlers.CToString(inq.Value.ProductIdentification).Trim();
|
||||
deviceInfo.Bus = simName == "ata" || simName == "ahcich" ? "ATAPI" : "SCSI";
|
||||
deviceInfo.Vendor = StringHandlers.CToString(inq.Value.VendorIdentification).Trim();
|
||||
deviceInfo.Model = StringHandlers.CToString(inq.Value.ProductIdentification).Trim();
|
||||
deviceInfo.Bus = simName == "ata" || simName == "ahcich" ? "ATAPI" : "SCSI";
|
||||
deviceInfo.Supported = simName != "ata";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case CamProto.ProtoNvme:
|
||||
deviceInfo.Bus = "NVMe";
|
||||
deviceInfo.Bus = "NVMe";
|
||||
deviceInfo.Supported = false;
|
||||
break;
|
||||
case CamProto.ProtoMmcsd:
|
||||
deviceInfo.Model = "Unknown card";
|
||||
deviceInfo.Bus = "MMC/SD";
|
||||
deviceInfo.Model = "Unknown card";
|
||||
deviceInfo.Bus = "MMC/SD";
|
||||
deviceInfo.Supported = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -50,19 +50,19 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
struct AtaCmd
|
||||
{
|
||||
public CamAtaIoFlags flags;
|
||||
public byte command;
|
||||
public byte features;
|
||||
public byte lba_low;
|
||||
public byte lba_mid;
|
||||
public byte lba_high;
|
||||
public byte device;
|
||||
public byte lba_low_exp;
|
||||
public byte lba_mid_exp;
|
||||
public byte lba_high_exp;
|
||||
public byte features_exp;
|
||||
public byte sector_count;
|
||||
public byte sector_count_exp;
|
||||
public byte control;
|
||||
public byte command;
|
||||
public byte features;
|
||||
public byte lba_low;
|
||||
public byte lba_mid;
|
||||
public byte lba_high;
|
||||
public byte device;
|
||||
public byte lba_low_exp;
|
||||
public byte lba_mid_exp;
|
||||
public byte lba_high_exp;
|
||||
public byte features_exp;
|
||||
public byte sector_count;
|
||||
public byte sector_count_exp;
|
||||
public byte control;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -70,17 +70,17 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
struct AtaRes
|
||||
{
|
||||
public CamAtaIoFlags flags;
|
||||
public byte status;
|
||||
public byte error;
|
||||
public byte lba_low;
|
||||
public byte lba_mid;
|
||||
public byte lba_high;
|
||||
public byte device;
|
||||
public byte lba_low_exp;
|
||||
public byte lba_mid_exp;
|
||||
public byte lba_high_exp;
|
||||
public byte sector_count;
|
||||
public byte sector_count_exp;
|
||||
public byte status;
|
||||
public byte error;
|
||||
public byte lba_low;
|
||||
public byte lba_mid;
|
||||
public byte lba_high;
|
||||
public byte device;
|
||||
public byte lba_low_exp;
|
||||
public byte lba_mid_exp;
|
||||
public byte lba_high_exp;
|
||||
public byte sector_count;
|
||||
public byte sector_count_exp;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -89,7 +89,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
{
|
||||
public uint priority;
|
||||
public uint generation;
|
||||
public int index;
|
||||
public int index;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
@@ -140,9 +140,9 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct CamqEntry
|
||||
{
|
||||
[FieldOffset(0)] public ListEntry le;
|
||||
[FieldOffset(0)] public SlistEntry sle;
|
||||
[FieldOffset(0)] public TailqEntry tqe;
|
||||
[FieldOffset(0)] public ListEntry le;
|
||||
[FieldOffset(0)] public SlistEntry sle;
|
||||
[FieldOffset(0)] public TailqEntry tqe;
|
||||
[FieldOffset(0)] public StailqEntry stqe;
|
||||
}
|
||||
|
||||
@@ -168,34 +168,37 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct CcbHdr
|
||||
{
|
||||
public CamPinfo pinfo;
|
||||
public CamPinfo pinfo;
|
||||
public CamqEntry xpt_links;
|
||||
public CamqEntry sim_links;
|
||||
public CamqEntry periph_links;
|
||||
public uint retry_count;
|
||||
public IntPtr cbfcnp;
|
||||
public uint retry_count;
|
||||
public IntPtr cbfcnp;
|
||||
public XptOpcode func_code;
|
||||
public CamStatus status;
|
||||
public IntPtr path;
|
||||
public uint path_id;
|
||||
public uint target_id;
|
||||
public ulong target_lun;
|
||||
public CcbFlags flags;
|
||||
public uint xflags;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public IntPtr[] periph_priv;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public IntPtr[] sim_priv;
|
||||
public IntPtr path;
|
||||
public uint path_id;
|
||||
public uint target_id;
|
||||
public ulong target_lun;
|
||||
public CcbFlags flags;
|
||||
public uint xflags;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public IntPtr[] periph_priv;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public IntPtr[] sim_priv;
|
||||
public CcbQosArea qos;
|
||||
public uint timeout;
|
||||
public Timeval softtimeout;
|
||||
public uint timeout;
|
||||
public Timeval softtimeout;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct ScsiSenseData
|
||||
{
|
||||
const int SSD_FULL_SIZE = 252;
|
||||
const int SSD_FULL_SIZE = 252;
|
||||
public byte error_code;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SSD_FULL_SIZE - 1)] public byte[] sense_buf;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SSD_FULL_SIZE - 1)]
|
||||
public byte[] sense_buf;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -232,7 +235,8 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// Area for the CDB send, or pointer to the CDB bytes to send
|
||||
/// </summary>
|
||||
const int IOCDBLEN = 16;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = IOCDBLEN)] public byte[] cdb_bytes;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = IOCDBLEN)]
|
||||
public byte[] cdb_bytes;
|
||||
/// <summary>Pointer to the message buffer</summary>
|
||||
public IntPtr msg_ptr;
|
||||
/// <summary>Number of bytes for the Message</summary>
|
||||
@@ -283,7 +287,8 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// Area for the CDB send, or pointer to the CDB bytes to send
|
||||
/// </summary>
|
||||
const int IOCDBLEN = 16;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = IOCDBLEN)] public byte[] cdb_bytes;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = IOCDBLEN)]
|
||||
public byte[] cdb_bytes;
|
||||
/// <summary>Pointer to the message buffer</summary>
|
||||
public IntPtr msg_ptr;
|
||||
/// <summary>Number of bytes for the Message</summary>
|
||||
@@ -496,11 +501,12 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
{
|
||||
const int DEV_IDLEN = 16;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN)] public byte[] periph_name;
|
||||
public uint unit_number;
|
||||
public path_id_t path_id;
|
||||
public target_id_t target_id;
|
||||
public lun_id_t target_lun;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN)]
|
||||
public byte[] periph_name;
|
||||
public uint unit_number;
|
||||
public path_id_t path_id;
|
||||
public target_id_t target_id;
|
||||
public lun_id_t target_lun;
|
||||
public PeriphPatternFlags flags;
|
||||
}
|
||||
|
||||
@@ -509,21 +515,25 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
struct DeviceIdMatchPattern
|
||||
{
|
||||
public byte id_len;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] id;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public byte[] id;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct ScsiStaticInquiryPattern
|
||||
{
|
||||
const int SID_VENDOR_SIZE = 8;
|
||||
const int SID_PRODUCT_SIZE = 16;
|
||||
const int SID_REVISION_SIZE = 4;
|
||||
const int SID_VENDOR_SIZE = 8;
|
||||
const int SID_PRODUCT_SIZE = 16;
|
||||
const int SID_REVISION_SIZE = 4;
|
||||
public byte type;
|
||||
public byte media_type;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SID_VENDOR_SIZE + 1)] public byte[] vendor;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SID_PRODUCT_SIZE + 1)] public byte[] product;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SID_REVISION_SIZE + 1)] public byte[] revision;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SID_VENDOR_SIZE + 1)]
|
||||
public byte[] vendor;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SID_PRODUCT_SIZE + 1)]
|
||||
public byte[] product;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SID_REVISION_SIZE + 1)]
|
||||
public byte[] revision;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
@@ -531,17 +541,17 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
struct DeviceMatchPatternData
|
||||
{
|
||||
[FieldOffset(0)] public ScsiStaticInquiryPattern inq_pat;
|
||||
[FieldOffset(0)] public DeviceIdMatchPattern devid_pat;
|
||||
[FieldOffset(0)] public DeviceIdMatchPattern devid_pat;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct DeviceMatchPattern
|
||||
{
|
||||
public uint path_id;
|
||||
public uint target_id;
|
||||
public uint target_lun;
|
||||
public DevPatternFlags flags;
|
||||
public uint path_id;
|
||||
public uint target_id;
|
||||
public uint target_lun;
|
||||
public DevPatternFlags flags;
|
||||
public DeviceMatchPatternData data;
|
||||
}
|
||||
|
||||
@@ -552,9 +562,10 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
const int DEV_IDLEN = 16;
|
||||
|
||||
public path_id_t path_id;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN)] public byte[] dev_name;
|
||||
public uint unit_number;
|
||||
public uint bus_id;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN)]
|
||||
public byte[] dev_name;
|
||||
public uint unit_number;
|
||||
public uint bus_id;
|
||||
BusPatternFlags flags;
|
||||
}
|
||||
|
||||
@@ -564,7 +575,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
{
|
||||
[FieldOffset(0)] public PeriphMatchPattern periph_pattern;
|
||||
[FieldOffset(0)] public DeviceMatchPattern device_pattern;
|
||||
[FieldOffset(0)] public BusMatchPattern bus_pattern;
|
||||
[FieldOffset(0)] public BusMatchPattern bus_pattern;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -579,11 +590,12 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct PeriphMatchResult
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] periph_name;
|
||||
public uint unit_number;
|
||||
public path_id_t path_id;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||
public byte[] periph_name;
|
||||
public uint unit_number;
|
||||
public path_id_t path_id;
|
||||
public target_id_t target_id;
|
||||
public lun_id_t target_lun;
|
||||
public lun_id_t target_lun;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -591,13 +603,14 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
struct MmcCid
|
||||
{
|
||||
public uint mid;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] pnm;
|
||||
public uint psn;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public byte[] pnm;
|
||||
public uint psn;
|
||||
public ushort oid;
|
||||
public ushort mdt_year;
|
||||
public byte mdt_month;
|
||||
public byte prv;
|
||||
public byte fwrev;
|
||||
public byte mdt_month;
|
||||
public byte prv;
|
||||
public byte fwrev;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -607,7 +620,8 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <summary>
|
||||
/// Card model
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] public byte[] model;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
|
||||
public byte[] model;
|
||||
|
||||
/// <summary>
|
||||
/// Card OCR
|
||||
@@ -622,7 +636,8 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <summary>
|
||||
/// Card CID -- raw
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public uint[] card_cid;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public uint[] card_cid;
|
||||
|
||||
/// <summary>
|
||||
/// Card CID -- parsed
|
||||
@@ -632,7 +647,8 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <summary>
|
||||
/// Card CSD -- raw
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public uint[] card_csd;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public uint[] card_csd;
|
||||
|
||||
/// <summary>
|
||||
/// Card RCA
|
||||
@@ -651,14 +667,16 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct DeviceMatchResult
|
||||
{
|
||||
public path_id_t path_id;
|
||||
public path_id_t path_id;
|
||||
public target_id_t target_id;
|
||||
public lun_id_t target_lun;
|
||||
public CamProto protocol;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] inq_data;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] public byte[] ident_data;
|
||||
public lun_id_t target_lun;
|
||||
public CamProto protocol;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public byte[] inq_data;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
|
||||
public byte[] ident_data;
|
||||
public DevResultFlags flags;
|
||||
public MmcParams mmc_ident_data;
|
||||
public MmcParams mmc_ident_data;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -666,8 +684,9 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
struct BusMatchResult
|
||||
{
|
||||
public path_id_t path_id;
|
||||
const int DEV_IDLEN = 16;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN)] public byte[] dev_name;
|
||||
const int DEV_IDLEN = 16;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN)]
|
||||
public byte[] dev_name;
|
||||
public uint unit_number;
|
||||
public uint bus_id;
|
||||
}
|
||||
@@ -678,7 +697,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
{
|
||||
[FieldOffset(0)] public PeriphMatchResult periph_result;
|
||||
[FieldOffset(0)] public DeviceMatchResult device_result;
|
||||
[FieldOffset(0)] public BusMatchResult bus_result;
|
||||
[FieldOffset(0)] public BusMatchResult bus_result;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -686,7 +705,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
struct DevMatchResult
|
||||
{
|
||||
public DevMatchType type;
|
||||
public MatchResult result;
|
||||
public MatchResult result;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -704,8 +723,9 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct CcbDevPosition
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public CamGenerations[] generations;
|
||||
DevPosType position_type;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public CamGenerations[] generations;
|
||||
DevPosType position_type;
|
||||
public CcbDmCookie cookie;
|
||||
}
|
||||
|
||||
@@ -713,10 +733,10 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct CcbDevMatch
|
||||
{
|
||||
public CcbHdr ccb_h;
|
||||
public CcbHdr ccb_h;
|
||||
CcbDevMatchStatus status;
|
||||
public uint num_patterns;
|
||||
public uint pattern_buf_len;
|
||||
public uint num_patterns;
|
||||
public uint pattern_buf_len;
|
||||
|
||||
/// <summary>
|
||||
/// dev_match_pattern*
|
||||
@@ -738,17 +758,19 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
struct CamDevice
|
||||
{
|
||||
const int MAXPATHLEN = 1024;
|
||||
const int DEV_IDLEN = 16;
|
||||
const int SIM_IDLEN = 16;
|
||||
const int DEV_IDLEN = 16;
|
||||
const int SIM_IDLEN = 16;
|
||||
/// <summary>
|
||||
/// Pathname of the device given by the user. This may be null if the user states the device name and unit number
|
||||
/// separately.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAXPATHLEN)] public byte[] DevicePath;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAXPATHLEN)]
|
||||
public byte[] DevicePath;
|
||||
/// <summary>
|
||||
/// Device name given by the user.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN + 1)] public byte[] GivenDevName;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN + 1)]
|
||||
public byte[] GivenDevName;
|
||||
/// <summary>
|
||||
/// Unit number given by the user.
|
||||
/// </summary>
|
||||
@@ -756,7 +778,8 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <summary>
|
||||
/// Name of the device, e.g. 'pass'
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN + 1)] public byte[] DeviceName;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DEV_IDLEN + 1)]
|
||||
public byte[] DeviceName;
|
||||
/// <summary>
|
||||
/// Unit number of the passthrough device associated with this particular device.
|
||||
/// </summary>
|
||||
@@ -764,7 +787,8 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <summary>
|
||||
/// Controller name, e.g. 'ahc'
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SIM_IDLEN + 1)] public byte[] SimName;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = SIM_IDLEN + 1)]
|
||||
public byte[] SimName;
|
||||
/// <summary>
|
||||
/// Controller unit number
|
||||
/// </summary>
|
||||
@@ -792,11 +816,13 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
/// <summary>
|
||||
/// SCSI Inquiry data
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] InqData;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public byte[] InqData;
|
||||
/// <summary>
|
||||
/// device serial number
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 252)] public byte[] SerialNum;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 252)]
|
||||
public byte[] SerialNum;
|
||||
/// <summary>
|
||||
/// length of the serial number
|
||||
/// </summary>
|
||||
@@ -823,19 +849,23 @@ namespace DiscImageChef.Devices.FreeBSD
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct CcbGetdev
|
||||
{
|
||||
public CcbHdr ccb_h;
|
||||
public CcbHdr ccb_h;
|
||||
public CamProto protocol;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] inq_data;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] public byte[] ident_data;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public byte[] inq_data;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
|
||||
public byte[] ident_data;
|
||||
/// <summary>
|
||||
/// device serial number
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 252)] public byte[] serial_num;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 252)]
|
||||
public byte[] serial_num;
|
||||
public byte inq_flags;
|
||||
/// <summary>
|
||||
/// length of the serial number
|
||||
/// </summary>
|
||||
public byte serial_num_len;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public IntPtr[] padding;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public IntPtr[] padding;
|
||||
}
|
||||
}
|
||||
@@ -46,15 +46,16 @@ namespace DiscImageChef.Devices.Linux
|
||||
/// <returns>List of devices</returns>
|
||||
internal static DeviceInfo[] GetList()
|
||||
{
|
||||
string[] sysdevs = Directory.GetFileSystemEntries(PATH_SYS_DEVBLOCK, "*", SearchOption.TopDirectoryOnly);
|
||||
string[] sysdevs =
|
||||
Directory.GetFileSystemEntries(PATH_SYS_DEVBLOCK, "*", SearchOption.TopDirectoryOnly);
|
||||
DeviceInfo[] devices = new DeviceInfo[sysdevs.Length];
|
||||
bool hasUdev;
|
||||
bool hasUdev;
|
||||
|
||||
IntPtr udev = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
udev = Extern.udev_new();
|
||||
udev = Extern.udev_new();
|
||||
hasUdev = udev != IntPtr.Zero;
|
||||
}
|
||||
catch { hasUdev = false; }
|
||||
@@ -68,7 +69,7 @@ namespace DiscImageChef.Devices.Linux
|
||||
IntPtr udevDev =
|
||||
Extern.udev_device_new_from_subsystem_sysname(udev, "block", Path.GetFileName(sysdevs[i]));
|
||||
devices[i].Vendor = Extern.udev_device_get_property_value(udevDev, "ID_VENDOR");
|
||||
devices[i].Model = Extern.udev_device_get_property_value(udevDev, "ID_MODEL");
|
||||
devices[i].Model = Extern.udev_device_get_property_value(udevDev, "ID_MODEL");
|
||||
if(!string.IsNullOrEmpty(devices[i].Model)) devices[i].Model = devices[i].Model.Replace('_', ' ');
|
||||
devices[i].Serial = Extern.udev_device_get_property_value(udevDev, "ID_SCSI_SERIAL");
|
||||
if(string.IsNullOrEmpty(devices[i].Serial))
|
||||
@@ -79,7 +80,7 @@ namespace DiscImageChef.Devices.Linux
|
||||
StreamReader sr;
|
||||
if(File.Exists(Path.Combine(sysdevs[i], "device/vendor")) && string.IsNullOrEmpty(devices[i].Vendor))
|
||||
{
|
||||
sr = new StreamReader(Path.Combine(sysdevs[i], "device/vendor"), Encoding.ASCII);
|
||||
sr = new StreamReader(Path.Combine(sysdevs[i], "device/vendor"), Encoding.ASCII);
|
||||
devices[i].Vendor = sr.ReadLine()?.Trim();
|
||||
}
|
||||
else if(devices[i].Path.StartsWith("/dev/loop", StringComparison.CurrentCulture))
|
||||
@@ -88,7 +89,7 @@ namespace DiscImageChef.Devices.Linux
|
||||
if(File.Exists(Path.Combine(sysdevs[i], "device/model")) &&
|
||||
(string.IsNullOrEmpty(devices[i].Model) || devices[i].Bus == "ata"))
|
||||
{
|
||||
sr = new StreamReader(Path.Combine(sysdevs[i], "device/model"), Encoding.ASCII);
|
||||
sr = new StreamReader(Path.Combine(sysdevs[i], "device/model"), Encoding.ASCII);
|
||||
devices[i].Model = sr.ReadLine()?.Trim();
|
||||
}
|
||||
else if(devices[i].Path.StartsWith("/dev/loop", StringComparison.CurrentCulture))
|
||||
@@ -96,7 +97,7 @@ namespace DiscImageChef.Devices.Linux
|
||||
|
||||
if(File.Exists(Path.Combine(sysdevs[i], "device/serial")) && string.IsNullOrEmpty(devices[i].Serial))
|
||||
{
|
||||
sr = new StreamReader(Path.Combine(sysdevs[i], "device/serial"), Encoding.ASCII);
|
||||
sr = new StreamReader(Path.Combine(sysdevs[i], "device/serial"), Encoding.ASCII);
|
||||
devices[i].Serial = sr.ReadLine()?.Trim();
|
||||
}
|
||||
|
||||
@@ -107,7 +108,7 @@ namespace DiscImageChef.Devices.Linux
|
||||
if(pieces.Length > 1)
|
||||
{
|
||||
devices[i].Vendor = pieces[0];
|
||||
devices[i].Model = devices[i].Model.Substring(pieces[0].Length + 1);
|
||||
devices[i].Model = devices[i].Model.Substring(pieces[0].Length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,28 +44,28 @@ namespace DiscImageChef.Devices.Linux
|
||||
/// <summary>
|
||||
/// Always 'S' for SG v3
|
||||
/// </summary>
|
||||
public int interface_id; /* [i] 'S' (required) */
|
||||
public int interface_id; /* [i] 'S' (required) */
|
||||
public ScsiIoctlDirection dxfer_direction; /* [i] */
|
||||
public byte cmd_len; /* [i] */
|
||||
public byte mx_sb_len; /* [i] */
|
||||
public ushort iovec_count; /* [i] */
|
||||
public uint dxfer_len; /* [i] */
|
||||
public IntPtr dxferp; /* [i], [*io] */
|
||||
public IntPtr cmdp; /* [i], [*i] */
|
||||
public IntPtr sbp; /* [i], [*o] */
|
||||
public uint timeout; /* [i] unit: millisecs */
|
||||
public uint flags; /* [i] */
|
||||
public int pack_id; /* [i->o] */
|
||||
public IntPtr usr_ptr; /* [i->o] */
|
||||
public byte status; /* [o] */
|
||||
public byte masked_status; /* [o] */
|
||||
public byte msg_status; /* [o] */
|
||||
public byte sb_len_wr; /* [o] */
|
||||
public ushort host_status; /* [o] */
|
||||
public ushort driver_status; /* [o] */
|
||||
public int resid; /* [o] */
|
||||
public uint duration; /* [o] */
|
||||
public SgInfo info; /* [o] */
|
||||
public byte cmd_len; /* [i] */
|
||||
public byte mx_sb_len; /* [i] */
|
||||
public ushort iovec_count; /* [i] */
|
||||
public uint dxfer_len; /* [i] */
|
||||
public IntPtr dxferp; /* [i], [*io] */
|
||||
public IntPtr cmdp; /* [i], [*i] */
|
||||
public IntPtr sbp; /* [i], [*o] */
|
||||
public uint timeout; /* [i] unit: millisecs */
|
||||
public uint flags; /* [i] */
|
||||
public int pack_id; /* [i->o] */
|
||||
public IntPtr usr_ptr; /* [i->o] */
|
||||
public byte status; /* [o] */
|
||||
public byte masked_status; /* [o] */
|
||||
public byte msg_status; /* [o] */
|
||||
public byte sb_len_wr; /* [o] */
|
||||
public ushort host_status; /* [o] */
|
||||
public ushort driver_status; /* [o] */
|
||||
public int resid; /* [o] */
|
||||
public uint duration; /* [o] */
|
||||
public SgInfo info; /* [o] */
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -85,10 +85,11 @@ namespace DiscImageChef.Devices.Linux
|
||||
/// <summary>
|
||||
/// CMD response
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public uint[] response;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public uint[] response;
|
||||
public MmcFlags flags;
|
||||
public uint blksz;
|
||||
public uint blocks;
|
||||
public uint blksz;
|
||||
public uint blocks;
|
||||
/// <summary>
|
||||
/// Sleep at least <see cref="postsleep_min_us" /> useconds, and at most
|
||||
/// <see cref="postsleep_max_us" /> useconds *after* issuing command.Needed for
|
||||
|
||||
@@ -58,13 +58,14 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI
|
||||
/// sense
|
||||
/// </param>
|
||||
internal static int SendScsiCommand(SafeFileHandle fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer,
|
||||
uint timeout, ScsiIoctlDirection direction, out double duration,
|
||||
out bool sense)
|
||||
internal static int SendScsiCommand(SafeFileHandle fd, byte[] cdb, ref byte[] buffer,
|
||||
out byte[] senseBuffer,
|
||||
uint timeout, ScsiIoctlDirection direction, out double duration,
|
||||
out bool sense)
|
||||
{
|
||||
senseBuffer = null;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
|
||||
if(buffer == null) return -1;
|
||||
|
||||
@@ -73,21 +74,21 @@ namespace DiscImageChef.Devices.Windows
|
||||
SenseBuf = new byte[32],
|
||||
sptd = new ScsiPassThroughDirect
|
||||
{
|
||||
Cdb = new byte[16],
|
||||
CdbLength = (byte)cdb.Length,
|
||||
SenseInfoLength = 32,
|
||||
DataIn = direction,
|
||||
Cdb = new byte[16],
|
||||
CdbLength = (byte)cdb.Length,
|
||||
SenseInfoLength = 32,
|
||||
DataIn = direction,
|
||||
DataTransferLength = (uint)buffer.Length,
|
||||
TimeOutValue = timeout,
|
||||
DataBuffer = Marshal.AllocHGlobal(buffer.Length)
|
||||
TimeOutValue = timeout,
|
||||
DataBuffer = Marshal.AllocHGlobal(buffer.Length)
|
||||
}
|
||||
};
|
||||
sptdSb.sptd.Length = (ushort)Marshal.SizeOf(sptdSb.sptd);
|
||||
sptdSb.sptd.Length = (ushort)Marshal.SizeOf(sptdSb.sptd);
|
||||
sptdSb.sptd.SenseInfoOffset = (uint)Marshal.SizeOf(sptdSb.sptd);
|
||||
Array.Copy(cdb, sptdSb.sptd.Cdb, cdb.Length);
|
||||
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
|
||||
Marshal.Copy(buffer, 0, sptdSb.sptd.DataBuffer, buffer.Length);
|
||||
|
||||
@@ -125,12 +126,13 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <param name="registers">Registers to send to drive</param>
|
||||
/// <param name="errorRegisters">Registers returned by drive</param>
|
||||
/// <param name="protocol">ATA protocol to use</param>
|
||||
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
errorRegisters = new AtaErrorRegistersChs();
|
||||
|
||||
if(buffer == null) return -1;
|
||||
@@ -141,19 +143,19 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
aptd = new AtaPassThroughDirect
|
||||
{
|
||||
TimeOutValue = timeout,
|
||||
DataBuffer = (IntPtr)offsetForBuffer,
|
||||
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
|
||||
TimeOutValue = timeout,
|
||||
DataBuffer = (IntPtr)offsetForBuffer,
|
||||
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
|
||||
DataTransferLength = (uint)buffer.Length,
|
||||
PreviousTaskFile = new AtaTaskFile(),
|
||||
PreviousTaskFile = new AtaTaskFile(),
|
||||
CurrentTaskFile = new AtaTaskFile
|
||||
{
|
||||
Command = registers.Command,
|
||||
Command = registers.Command,
|
||||
CylinderHigh = registers.CylinderHigh,
|
||||
CylinderLow = registers.CylinderLow,
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = registers.Feature,
|
||||
SectorCount = registers.SectorCount,
|
||||
CylinderLow = registers.CylinderLow,
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = registers.Feature,
|
||||
SectorCount = registers.SectorCount,
|
||||
SectorNumber = registers.Sector
|
||||
}
|
||||
},
|
||||
@@ -187,8 +189,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
// Unknown if needed
|
||||
aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
|
||||
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
|
||||
Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length);
|
||||
|
||||
@@ -205,12 +207,12 @@ namespace DiscImageChef.Devices.Windows
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
|
||||
errorRegisters.CylinderHigh = aptdBuf.aptd.CurrentTaskFile.CylinderHigh;
|
||||
errorRegisters.CylinderLow = aptdBuf.aptd.CurrentTaskFile.CylinderLow;
|
||||
errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
|
||||
errorRegisters.Sector = aptdBuf.aptd.CurrentTaskFile.SectorNumber;
|
||||
errorRegisters.SectorCount = aptdBuf.aptd.CurrentTaskFile.SectorCount;
|
||||
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
|
||||
errorRegisters.CylinderLow = aptdBuf.aptd.CurrentTaskFile.CylinderLow;
|
||||
errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
|
||||
errorRegisters.Sector = aptdBuf.aptd.CurrentTaskFile.SectorNumber;
|
||||
errorRegisters.SectorCount = aptdBuf.aptd.CurrentTaskFile.SectorCount;
|
||||
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
|
||||
|
||||
sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0;
|
||||
|
||||
@@ -229,12 +231,13 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <param name="registers">Registers to send to drive</param>
|
||||
/// <param name="errorRegisters">Registers returned by drive</param>
|
||||
/// <param name="protocol">ATA protocol to use</param>
|
||||
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
errorRegisters = new AtaErrorRegistersLba28();
|
||||
|
||||
if(buffer == null) return -1;
|
||||
@@ -245,19 +248,19 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
aptd = new AtaPassThroughDirect
|
||||
{
|
||||
TimeOutValue = timeout,
|
||||
DataBuffer = (IntPtr)offsetForBuffer,
|
||||
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
|
||||
TimeOutValue = timeout,
|
||||
DataBuffer = (IntPtr)offsetForBuffer,
|
||||
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
|
||||
DataTransferLength = (uint)buffer.Length,
|
||||
PreviousTaskFile = new AtaTaskFile(),
|
||||
PreviousTaskFile = new AtaTaskFile(),
|
||||
CurrentTaskFile = new AtaTaskFile
|
||||
{
|
||||
Command = registers.Command,
|
||||
Command = registers.Command,
|
||||
CylinderHigh = registers.LbaHigh,
|
||||
CylinderLow = registers.LbaMid,
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = registers.Feature,
|
||||
SectorCount = registers.SectorCount,
|
||||
CylinderLow = registers.LbaMid,
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = registers.Feature,
|
||||
SectorCount = registers.SectorCount,
|
||||
SectorNumber = registers.LbaLow
|
||||
}
|
||||
},
|
||||
@@ -291,8 +294,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
// Unknown if needed
|
||||
aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
|
||||
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
|
||||
Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length);
|
||||
|
||||
@@ -308,13 +311,13 @@ namespace DiscImageChef.Devices.Windows
|
||||
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
|
||||
errorRegisters.LbaHigh = aptdBuf.aptd.CurrentTaskFile.CylinderHigh;
|
||||
errorRegisters.LbaMid = aptdBuf.aptd.CurrentTaskFile.CylinderLow;
|
||||
errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
|
||||
errorRegisters.LbaLow = aptdBuf.aptd.CurrentTaskFile.SectorNumber;
|
||||
errorRegisters.LbaHigh = aptdBuf.aptd.CurrentTaskFile.CylinderHigh;
|
||||
errorRegisters.LbaMid = aptdBuf.aptd.CurrentTaskFile.CylinderLow;
|
||||
errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
|
||||
errorRegisters.LbaLow = aptdBuf.aptd.CurrentTaskFile.SectorNumber;
|
||||
errorRegisters.SectorCount = aptdBuf.aptd.CurrentTaskFile.SectorCount;
|
||||
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
|
||||
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
|
||||
|
||||
sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0;
|
||||
|
||||
@@ -333,12 +336,13 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <param name="registers">Registers to send to drive</param>
|
||||
/// <param name="errorRegisters">Registers returned by drive</param>
|
||||
/// <param name="protocol">ATA protocol to use</param>
|
||||
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba48 registers,
|
||||
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout, out double duration, out bool sense)
|
||||
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba48 registers,
|
||||
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
errorRegisters = new AtaErrorRegistersLba48();
|
||||
|
||||
if(buffer == null) return -1;
|
||||
@@ -349,28 +353,28 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
aptd = new AtaPassThroughDirect
|
||||
{
|
||||
TimeOutValue = timeout,
|
||||
DataBuffer = (IntPtr)offsetForBuffer,
|
||||
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
|
||||
TimeOutValue = timeout,
|
||||
DataBuffer = (IntPtr)offsetForBuffer,
|
||||
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
|
||||
DataTransferLength = (uint)buffer.Length,
|
||||
PreviousTaskFile =
|
||||
new AtaTaskFile
|
||||
{
|
||||
CylinderHigh = (byte)((registers.LbaHigh & 0xFF00) >> 8),
|
||||
CylinderLow = (byte)((registers.LbaMid & 0xFF00) >> 8),
|
||||
Features = (byte)((registers.Feature & 0xFF00) >> 8),
|
||||
SectorCount = (byte)((registers.SectorCount & 0xFF00) >> 8),
|
||||
SectorNumber = (byte)((registers.LbaLow & 0xFF00) >> 8)
|
||||
CylinderHigh = (byte)((registers.LbaHigh & 0xFF00) >> 8),
|
||||
CylinderLow = (byte)((registers.LbaMid & 0xFF00) >> 8),
|
||||
Features = (byte)((registers.Feature & 0xFF00) >> 8),
|
||||
SectorCount = (byte)((registers.SectorCount & 0xFF00) >> 8),
|
||||
SectorNumber = (byte)((registers.LbaLow & 0xFF00) >> 8)
|
||||
},
|
||||
CurrentTaskFile = new AtaTaskFile
|
||||
{
|
||||
Command = registers.Command,
|
||||
Command = registers.Command,
|
||||
CylinderHigh = (byte)(registers.LbaHigh & 0xFF),
|
||||
CylinderLow = (byte)(registers.LbaMid & 0xFF),
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = (byte)(registers.Feature & 0xFF),
|
||||
SectorCount = (byte)(registers.SectorCount & 0xFF),
|
||||
SectorNumber = (byte)(registers.LbaLow & 0xFF)
|
||||
CylinderLow = (byte)(registers.LbaMid & 0xFF),
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = (byte)(registers.Feature & 0xFF),
|
||||
SectorCount = (byte)(registers.SectorCount & 0xFF),
|
||||
SectorNumber = (byte)(registers.LbaLow & 0xFF)
|
||||
}
|
||||
},
|
||||
dataBuffer = new byte[64 * 512]
|
||||
@@ -403,8 +407,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
// Unknown if needed
|
||||
aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
|
||||
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
|
||||
Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length);
|
||||
|
||||
@@ -429,8 +433,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
errorRegisters.LbaHigh = (ushort)((aptdBuf.aptd.PreviousTaskFile.CylinderHigh << 8) +
|
||||
aptdBuf.aptd.CurrentTaskFile.CylinderHigh);
|
||||
errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
|
||||
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
|
||||
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
|
||||
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
|
||||
|
||||
sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0;
|
||||
|
||||
@@ -449,12 +453,13 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <param name="registers">Registers to send to drive</param>
|
||||
/// <param name="errorRegisters">Registers returned by drive</param>
|
||||
/// <param name="protocol">ATA protocol to use</param>
|
||||
internal static int SendIdeCommand(SafeFileHandle fd, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout, out double duration, out bool sense)
|
||||
internal static int SendIdeCommand(SafeFileHandle fd, AtaRegistersChs registers,
|
||||
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
errorRegisters = new AtaErrorRegistersChs();
|
||||
|
||||
if(buffer == null || buffer.Length > 512) return -1;
|
||||
@@ -463,20 +468,20 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
CurrentTaskFile = new AtaTaskFile
|
||||
{
|
||||
Command = registers.Command,
|
||||
Command = registers.Command,
|
||||
CylinderHigh = registers.CylinderHigh,
|
||||
CylinderLow = registers.CylinderLow,
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = registers.Feature,
|
||||
SectorCount = registers.SectorCount,
|
||||
CylinderLow = registers.CylinderLow,
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = registers.Feature,
|
||||
SectorCount = registers.SectorCount,
|
||||
SectorNumber = registers.Sector
|
||||
},
|
||||
DataBufferSize = 512,
|
||||
DataBuffer = new byte[512]
|
||||
DataBuffer = new byte[512]
|
||||
};
|
||||
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
|
||||
Array.Copy(buffer, 0, iptd.DataBuffer, 0, buffer.Length);
|
||||
|
||||
@@ -494,12 +499,12 @@ namespace DiscImageChef.Devices.Windows
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
|
||||
errorRegisters.CylinderHigh = iptd.CurrentTaskFile.CylinderHigh;
|
||||
errorRegisters.CylinderLow = iptd.CurrentTaskFile.CylinderLow;
|
||||
errorRegisters.DeviceHead = iptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = iptd.CurrentTaskFile.Error;
|
||||
errorRegisters.Sector = iptd.CurrentTaskFile.SectorNumber;
|
||||
errorRegisters.SectorCount = iptd.CurrentTaskFile.SectorCount;
|
||||
errorRegisters.Status = iptd.CurrentTaskFile.Status;
|
||||
errorRegisters.CylinderLow = iptd.CurrentTaskFile.CylinderLow;
|
||||
errorRegisters.DeviceHead = iptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = iptd.CurrentTaskFile.Error;
|
||||
errorRegisters.Sector = iptd.CurrentTaskFile.SectorNumber;
|
||||
errorRegisters.SectorCount = iptd.CurrentTaskFile.SectorCount;
|
||||
errorRegisters.Status = iptd.CurrentTaskFile.Status;
|
||||
|
||||
sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0;
|
||||
|
||||
@@ -518,12 +523,13 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <param name="registers">Registers to send to drive</param>
|
||||
/// <param name="errorRegisters">Registers returned by drive</param>
|
||||
/// <param name="protocol">ATA protocol to use</param>
|
||||
internal static int SendIdeCommand(SafeFileHandle fd, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout, out double duration, out bool sense)
|
||||
internal static int SendIdeCommand(SafeFileHandle fd, AtaRegistersLba28 registers,
|
||||
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
|
||||
ref byte[] buffer, uint timeout,
|
||||
out double duration, out bool sense)
|
||||
{
|
||||
duration = 0;
|
||||
sense = false;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
errorRegisters = new AtaErrorRegistersLba28();
|
||||
|
||||
if(buffer == null) return -1;
|
||||
@@ -532,20 +538,20 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
CurrentTaskFile = new AtaTaskFile
|
||||
{
|
||||
Command = registers.Command,
|
||||
Command = registers.Command,
|
||||
CylinderHigh = registers.LbaHigh,
|
||||
CylinderLow = registers.LbaMid,
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = registers.Feature,
|
||||
SectorCount = registers.SectorCount,
|
||||
CylinderLow = registers.LbaMid,
|
||||
DeviceHead = registers.DeviceHead,
|
||||
Features = registers.Feature,
|
||||
SectorCount = registers.SectorCount,
|
||||
SectorNumber = registers.LbaLow
|
||||
},
|
||||
DataBufferSize = 512,
|
||||
DataBuffer = new byte[512]
|
||||
DataBuffer = new byte[512]
|
||||
};
|
||||
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
uint k = 0;
|
||||
int error = 0;
|
||||
|
||||
Array.Copy(buffer, 0, iptd.DataBuffer, 0, buffer.Length);
|
||||
|
||||
@@ -562,13 +568,13 @@ namespace DiscImageChef.Devices.Windows
|
||||
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
|
||||
errorRegisters.LbaHigh = iptd.CurrentTaskFile.CylinderHigh;
|
||||
errorRegisters.LbaMid = iptd.CurrentTaskFile.CylinderLow;
|
||||
errorRegisters.DeviceHead = iptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = iptd.CurrentTaskFile.Error;
|
||||
errorRegisters.LbaLow = iptd.CurrentTaskFile.SectorNumber;
|
||||
errorRegisters.LbaHigh = iptd.CurrentTaskFile.CylinderHigh;
|
||||
errorRegisters.LbaMid = iptd.CurrentTaskFile.CylinderLow;
|
||||
errorRegisters.DeviceHead = iptd.CurrentTaskFile.DeviceHead;
|
||||
errorRegisters.Error = iptd.CurrentTaskFile.Error;
|
||||
errorRegisters.LbaLow = iptd.CurrentTaskFile.SectorNumber;
|
||||
errorRegisters.SectorCount = iptd.CurrentTaskFile.SectorCount;
|
||||
errorRegisters.Status = iptd.CurrentTaskFile.Status;
|
||||
errorRegisters.Status = iptd.CurrentTaskFile.Status;
|
||||
|
||||
sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0;
|
||||
|
||||
@@ -583,7 +589,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
static uint GetDeviceNumber(SafeFileHandle deviceHandle)
|
||||
{
|
||||
StorageDeviceNumber sdn = new StorageDeviceNumber {deviceNumber = -1};
|
||||
uint k = 0;
|
||||
uint k = 0;
|
||||
if(!Extern.DeviceIoControlGetDeviceNumber(deviceHandle, WindowsIoctl.IoctlStorageGetDeviceNumber,
|
||||
IntPtr.Zero, 0, ref sdn, (uint)Marshal.SizeOf(sdn), ref k,
|
||||
IntPtr.Zero)) return uint.MaxValue;
|
||||
@@ -609,7 +615,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
|
||||
if(hDevInfo.IsInvalid) return null;
|
||||
|
||||
uint index = 0;
|
||||
uint index = 0;
|
||||
DeviceInterfaceData spdid = new DeviceInterfaceData();
|
||||
spdid.cbSize = Marshal.SizeOf(spdid);
|
||||
|
||||
@@ -700,19 +706,22 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <param name="argument">Command argument</param>
|
||||
/// <param name="response">Response registers</param>
|
||||
/// <param name="blockSize">Size of block in bytes</param>
|
||||
internal static int SendMmcCommand(SafeFileHandle fd, MmcCommands command, bool write, bool isApplication,
|
||||
MmcFlags flags, uint argument, uint blockSize, uint blocks,
|
||||
ref byte[] buffer, out uint[] response, out double duration, out bool sense,
|
||||
uint timeout = 0)
|
||||
internal static int SendMmcCommand(SafeFileHandle fd, MmcCommands command, bool write,
|
||||
bool isApplication,
|
||||
MmcFlags flags, uint argument, uint blockSize,
|
||||
uint blocks,
|
||||
ref byte[] buffer, out uint[] response, out double duration,
|
||||
out bool sense,
|
||||
uint timeout = 0)
|
||||
{
|
||||
SffdiskDeviceCommandData commandData = new SffdiskDeviceCommandData();
|
||||
SdCmdDescriptor commandDescriptor = new SdCmdDescriptor();
|
||||
commandData.size = (ushort)Marshal.SizeOf(commandData);
|
||||
commandData.command = SffdiskDcmd.DeviceCommand;
|
||||
commandData.protocolArgumentSize = (ushort)Marshal.SizeOf(commandDescriptor);
|
||||
commandData.deviceDataBufferSize = blockSize * blocks;
|
||||
commandDescriptor.commandCode = (byte)command;
|
||||
commandDescriptor.cmdClass = isApplication ? SdCommandClass.AppCmd : SdCommandClass.Standard;
|
||||
SffdiskDeviceCommandData commandData = new SffdiskDeviceCommandData();
|
||||
SdCmdDescriptor commandDescriptor = new SdCmdDescriptor();
|
||||
commandData.size = (ushort)Marshal.SizeOf(commandData);
|
||||
commandData.command = SffdiskDcmd.DeviceCommand;
|
||||
commandData.protocolArgumentSize = (ushort)Marshal.SizeOf(commandDescriptor);
|
||||
commandData.deviceDataBufferSize = blockSize * blocks;
|
||||
commandDescriptor.commandCode = (byte)command;
|
||||
commandDescriptor.cmdClass = isApplication ? SdCommandClass.AppCmd : SdCommandClass.Standard;
|
||||
commandDescriptor.transferDirection = write ? SdTransferDirection.Write : SdTransferDirection.Read;
|
||||
commandDescriptor.transferType = flags.HasFlag(MmcFlags.CommandAdtc)
|
||||
? SdTransferType.SingleBlock
|
||||
@@ -742,7 +751,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
Marshal.Copy(hBuf, commandB, 0, commandB.Length);
|
||||
Marshal.FreeHGlobal(hBuf);
|
||||
|
||||
int error = 0;
|
||||
int error = 0;
|
||||
DateTime start = DateTime.Now;
|
||||
sense = !Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskDeviceCommand, commandB, (uint)commandB.Length,
|
||||
commandB, (uint)commandB.Length, out _, IntPtr.Zero);
|
||||
|
||||
@@ -327,7 +327,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
|
||||
enum WindowsIoctl : uint
|
||||
{
|
||||
IoctlAtaPassThrough = 0x4D02C,
|
||||
IoctlAtaPassThrough = 0x4D02C,
|
||||
IoctlAtaPassThroughDirect = 0x4D030,
|
||||
/// <summary>
|
||||
/// ScsiPassThrough
|
||||
@@ -341,11 +341,11 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// ScsiGetAddress
|
||||
/// </summary>
|
||||
IoctlScsiGetAddress = 0x41018,
|
||||
IoctlStorageQueryProperty = 0x2D1400,
|
||||
IoctlIdePassThrough = 0x4D028,
|
||||
IoctlStorageGetDeviceNumber = 0x2D1080,
|
||||
IoctlStorageQueryProperty = 0x2D1400,
|
||||
IoctlIdePassThrough = 0x4D028,
|
||||
IoctlStorageGetDeviceNumber = 0x2D1080,
|
||||
IoctlSffdiskQueryDeviceProtocol = 0x71E80,
|
||||
IoctlSffdiskDeviceCommand = 0x79E84
|
||||
IoctlSffdiskDeviceCommand = 0x79E84
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@@ -379,51 +379,51 @@ namespace DiscImageChef.Devices.Windows
|
||||
|
||||
enum StoragePropertyId
|
||||
{
|
||||
Device = 0,
|
||||
Adapter = 1,
|
||||
Id = 2,
|
||||
UniqueId = 3,
|
||||
WriteCache = 4,
|
||||
Miniport = 5,
|
||||
AccessAlignment = 6,
|
||||
SeekPenalty = 7,
|
||||
Trim = 8,
|
||||
Device = 0,
|
||||
Adapter = 1,
|
||||
Id = 2,
|
||||
UniqueId = 3,
|
||||
WriteCache = 4,
|
||||
Miniport = 5,
|
||||
AccessAlignment = 6,
|
||||
SeekPenalty = 7,
|
||||
Trim = 8,
|
||||
WriteAggregation = 9,
|
||||
Telemetry = 10,
|
||||
LbProvisioning = 11,
|
||||
Power = 12,
|
||||
Copyoffload = 13,
|
||||
Resiliency = 14
|
||||
Telemetry = 10,
|
||||
LbProvisioning = 11,
|
||||
Power = 12,
|
||||
Copyoffload = 13,
|
||||
Resiliency = 14
|
||||
}
|
||||
|
||||
enum StorageQueryType
|
||||
{
|
||||
Standard = 0,
|
||||
Exists = 1,
|
||||
Mask = 2,
|
||||
Max = 3
|
||||
Exists = 1,
|
||||
Mask = 2,
|
||||
Max = 3
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
enum StorageBusType
|
||||
{
|
||||
Unknown = 0,
|
||||
SCSI = 1,
|
||||
ATAPI = 2,
|
||||
ATA = 3,
|
||||
FireWire = 4,
|
||||
SSA = 5,
|
||||
Fibre = 6,
|
||||
USB = 7,
|
||||
RAID = 8,
|
||||
iSCSI = 9,
|
||||
SAS = 0xA,
|
||||
SATA = 0xB,
|
||||
SecureDigital = 0xC,
|
||||
MultiMediaCard = 0xD,
|
||||
Virtual = 0xE,
|
||||
Unknown = 0,
|
||||
SCSI = 1,
|
||||
ATAPI = 2,
|
||||
ATA = 3,
|
||||
FireWire = 4,
|
||||
SSA = 5,
|
||||
Fibre = 6,
|
||||
USB = 7,
|
||||
RAID = 8,
|
||||
iSCSI = 9,
|
||||
SAS = 0xA,
|
||||
SATA = 0xB,
|
||||
SecureDigital = 0xC,
|
||||
MultiMediaCard = 0xD,
|
||||
Virtual = 0xE,
|
||||
FileBackedVirtual = 0xF,
|
||||
NVMe = 0x11
|
||||
NVMe = 0x11
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -40,72 +40,99 @@ namespace DiscImageChef.Devices.Windows
|
||||
static class Extern
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
internal static extern SafeFileHandle CreateFile([MarshalAs(UnmanagedType.LPTStr)] string filename,
|
||||
[MarshalAs(UnmanagedType.U4)] FileAccess access,
|
||||
[MarshalAs(UnmanagedType.U4)] FileShare share,
|
||||
IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
|
||||
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
|
||||
internal static extern SafeFileHandle CreateFile([MarshalAs(UnmanagedType.LPTStr)] string filename,
|
||||
[MarshalAs(UnmanagedType.U4)] FileAccess access,
|
||||
[MarshalAs(UnmanagedType.U4)] FileShare share,
|
||||
IntPtr
|
||||
securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
|
||||
[MarshalAs(UnmanagedType.U4)]
|
||||
FileMode creationDisposition,
|
||||
[MarshalAs(UnmanagedType.U4)]
|
||||
FileAttributes flagsAndAttributes, IntPtr templateFile);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "DeviceIoControl", CharSet = CharSet.Auto)]
|
||||
internal static extern bool DeviceIoControlScsi(SafeFileHandle hDevice, WindowsIoctl ioControlCode,
|
||||
internal static extern bool DeviceIoControlScsi(SafeFileHandle hDevice,
|
||||
WindowsIoctl ioControlCode,
|
||||
ref ScsiPassThroughDirectAndSenseBuffer inBuffer,
|
||||
uint nInBufferSize,
|
||||
uint nInBufferSize,
|
||||
ref ScsiPassThroughDirectAndSenseBuffer outBuffer,
|
||||
uint nOutBufferSize, ref uint pBytesReturned,
|
||||
IntPtr overlapped);
|
||||
uint nOutBufferSize,
|
||||
ref uint pBytesReturned,
|
||||
IntPtr overlapped);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "DeviceIoControl", CharSet = CharSet.Auto)]
|
||||
internal static extern bool DeviceIoControlAta(SafeFileHandle hDevice, WindowsIoctl ioControlCode,
|
||||
ref AtaPassThroughDirectWithBuffer inBuffer, uint nInBufferSize,
|
||||
internal static extern bool DeviceIoControlAta(SafeFileHandle hDevice,
|
||||
WindowsIoctl ioControlCode,
|
||||
ref AtaPassThroughDirectWithBuffer inBuffer,
|
||||
uint nInBufferSize,
|
||||
ref AtaPassThroughDirectWithBuffer outBuffer,
|
||||
uint nOutBufferSize, ref uint pBytesReturned, IntPtr overlapped);
|
||||
uint nOutBufferSize,
|
||||
ref uint pBytesReturned, IntPtr overlapped);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "DeviceIoControl", CharSet = CharSet.Auto)]
|
||||
internal static extern bool DeviceIoControlStorageQuery(SafeFileHandle hDevice, WindowsIoctl ioControlCode,
|
||||
ref StoragePropertyQuery inBuffer, uint nInBufferSize,
|
||||
IntPtr outBuffer, uint nOutBufferSize,
|
||||
ref uint pBytesReturned, IntPtr overlapped);
|
||||
internal static extern bool DeviceIoControlStorageQuery(SafeFileHandle hDevice,
|
||||
WindowsIoctl ioControlCode,
|
||||
ref StoragePropertyQuery inBuffer,
|
||||
uint nInBufferSize,
|
||||
IntPtr outBuffer,
|
||||
uint nOutBufferSize,
|
||||
ref uint pBytesReturned,
|
||||
IntPtr overlapped);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "DeviceIoControl", CharSet = CharSet.Auto)]
|
||||
internal static extern bool DeviceIoControlIde(SafeFileHandle hDevice, WindowsIoctl ioControlCode,
|
||||
ref IdePassThroughDirect inBuffer, uint nInBufferSize,
|
||||
ref IdePassThroughDirect outBuffer, uint nOutBufferSize,
|
||||
ref uint pBytesReturned, IntPtr overlapped);
|
||||
internal static extern bool DeviceIoControlIde(SafeFileHandle hDevice,
|
||||
WindowsIoctl ioControlCode,
|
||||
ref IdePassThroughDirect inBuffer,
|
||||
uint nInBufferSize,
|
||||
ref IdePassThroughDirect outBuffer,
|
||||
uint nOutBufferSize,
|
||||
ref uint pBytesReturned,
|
||||
IntPtr overlapped);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "DeviceIoControl", CharSet = CharSet.Auto)]
|
||||
internal static extern bool DeviceIoControlGetDeviceNumber(SafeFileHandle hDevice, WindowsIoctl ioControlCode,
|
||||
IntPtr inBuffer, uint nInBufferSize,
|
||||
internal static extern bool DeviceIoControlGetDeviceNumber(SafeFileHandle hDevice,
|
||||
WindowsIoctl ioControlCode,
|
||||
IntPtr inBuffer,
|
||||
uint nInBufferSize,
|
||||
ref StorageDeviceNumber outBuffer,
|
||||
uint nOutBufferSize, ref uint pBytesReturned,
|
||||
IntPtr overlapped);
|
||||
uint nOutBufferSize,
|
||||
ref uint pBytesReturned,
|
||||
IntPtr overlapped);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "DeviceIoControl", CharSet = CharSet.Auto)]
|
||||
internal static extern bool DeviceIoControl(SafeFileHandle hDevice, WindowsIoctl ioControlCode, IntPtr inBuffer,
|
||||
uint nInBufferSize, ref SffdiskQueryDeviceProtocolData outBuffer,
|
||||
uint nOutBufferSize, out uint pBytesReturned, IntPtr overlapped);
|
||||
internal static extern bool DeviceIoControl(SafeFileHandle hDevice,
|
||||
WindowsIoctl ioControlCode, IntPtr inBuffer,
|
||||
uint nInBufferSize,
|
||||
ref SffdiskQueryDeviceProtocolData outBuffer,
|
||||
uint nOutBufferSize,
|
||||
out uint pBytesReturned,
|
||||
IntPtr overlapped);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "DeviceIoControl", CharSet = CharSet.Auto)]
|
||||
internal static extern bool DeviceIoControl(SafeFileHandle hDevice, WindowsIoctl ioControlCode, byte[] inBuffer,
|
||||
uint nInBufferSize, byte[] outBuffer, uint nOutBufferSize,
|
||||
out uint pBytesReturned, IntPtr overlapped);
|
||||
internal static extern bool DeviceIoControl(SafeFileHandle hDevice, WindowsIoctl ioControlCode,
|
||||
byte[] inBuffer,
|
||||
uint nInBufferSize, byte[] outBuffer,
|
||||
uint nOutBufferSize,
|
||||
out uint pBytesReturned, IntPtr overlapped);
|
||||
|
||||
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
|
||||
internal static extern SafeFileHandle SetupDiGetClassDevs(ref Guid classGuid, IntPtr enumerator,
|
||||
IntPtr hwndParent, DeviceGetClassFlags flags);
|
||||
internal static extern SafeFileHandle SetupDiGetClassDevs(ref Guid classGuid, IntPtr enumerator,
|
||||
IntPtr hwndParent, DeviceGetClassFlags flags);
|
||||
|
||||
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern bool SetupDiEnumDeviceInterfaces(SafeFileHandle hDevInfo, IntPtr devInfo,
|
||||
ref Guid interfaceClassGuid, uint memberIndex,
|
||||
public static extern bool SetupDiEnumDeviceInterfaces(SafeFileHandle hDevInfo,
|
||||
IntPtr devInfo,
|
||||
ref Guid interfaceClassGuid,
|
||||
uint memberIndex,
|
||||
ref DeviceInterfaceData deviceInterfaceData);
|
||||
|
||||
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern bool SetupDiGetDeviceInterfaceDetail(SafeFileHandle hDevInfo,
|
||||
public static extern bool SetupDiGetDeviceInterfaceDetail(SafeFileHandle hDevInfo,
|
||||
ref DeviceInterfaceData deviceInterfaceData,
|
||||
IntPtr deviceInterfaceDetailData,
|
||||
uint deviceInterfaceDetailDataSize,
|
||||
ref uint requiredSize, IntPtr deviceInfoData);
|
||||
IntPtr deviceInterfaceDetailData,
|
||||
uint deviceInterfaceDetailDataSize,
|
||||
ref uint requiredSize,
|
||||
IntPtr deviceInfoData);
|
||||
|
||||
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern bool SetupDiDestroyDeviceInfoList(SafeFileHandle hDevInfo);
|
||||
|
||||
@@ -50,8 +50,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <returns>Decoded string</returns>
|
||||
static string HexStringToString(string hex)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
const string HEXTABLE = "0123456789abcdef";
|
||||
StringBuilder result = new StringBuilder();
|
||||
const string HEXTABLE = "0123456789abcdef";
|
||||
|
||||
for(int i = 0; i < hex.Length / 2; i++)
|
||||
result.Append((char)(16 * HEXTABLE.IndexOf(hex[2 * i]) + HEXTABLE.IndexOf(hex[2 * i + 1])));
|
||||
@@ -77,20 +77,20 @@ namespace DiscImageChef.Devices.Windows
|
||||
deviceIDs.AddRange(from ManagementObject drive in objCol select (string)drive["DeviceID"]);
|
||||
|
||||
mgmtObjSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_TapeDrive");
|
||||
objCol = mgmtObjSearcher.Get();
|
||||
objCol = mgmtObjSearcher.Get();
|
||||
|
||||
deviceIDs.AddRange(from ManagementObject drive in objCol select (string)drive["DeviceID"]);
|
||||
|
||||
mgmtObjSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_CDROMDrive");
|
||||
objCol = mgmtObjSearcher.Get();
|
||||
objCol = mgmtObjSearcher.Get();
|
||||
|
||||
deviceIDs.AddRange(from ManagementObject drive in objCol select (string)drive["Drive"]);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG
|
||||
throw;
|
||||
#else
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
@@ -108,8 +108,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
|
||||
StoragePropertyQuery query = new StoragePropertyQuery
|
||||
{
|
||||
PropertyId = StoragePropertyId.Device,
|
||||
QueryType = StorageQueryType.Standard,
|
||||
PropertyId = StoragePropertyId.Device,
|
||||
QueryType = StorageQueryType.Standard,
|
||||
AdditionalParameters = new byte[1]
|
||||
};
|
||||
|
||||
@@ -117,10 +117,10 @@ namespace DiscImageChef.Devices.Windows
|
||||
//descriptor.RawDeviceProperties = new byte[16384];
|
||||
|
||||
IntPtr descriptorPtr = Marshal.AllocHGlobal(1000);
|
||||
byte[] descriptorB = new byte[1000];
|
||||
byte[] descriptorB = new byte[1000];
|
||||
|
||||
uint returned = 0;
|
||||
int error = 0;
|
||||
int error = 0;
|
||||
|
||||
bool hasError = !Extern.DeviceIoControlStorageQuery(fd, WindowsIoctl.IoctlStorageQueryProperty,
|
||||
ref query, (uint)Marshal.SizeOf(query),
|
||||
@@ -134,18 +134,18 @@ namespace DiscImageChef.Devices.Windows
|
||||
|
||||
StorageDeviceDescriptor descriptor = new StorageDeviceDescriptor
|
||||
{
|
||||
Version = BitConverter.ToUInt32(descriptorB, 0),
|
||||
Size = BitConverter.ToUInt32(descriptorB, 4),
|
||||
DeviceType = descriptorB[8],
|
||||
DeviceTypeModifier = descriptorB[9],
|
||||
RemovableMedia = BitConverter.ToBoolean(descriptorB, 10),
|
||||
CommandQueueing = BitConverter.ToBoolean(descriptorB, 11),
|
||||
VendorIdOffset = BitConverter.ToInt32(descriptorB, 12),
|
||||
ProductIdOffset = BitConverter.ToInt32(descriptorB, 16),
|
||||
Version = BitConverter.ToUInt32(descriptorB, 0),
|
||||
Size = BitConverter.ToUInt32(descriptorB, 4),
|
||||
DeviceType = descriptorB[8],
|
||||
DeviceTypeModifier = descriptorB[9],
|
||||
RemovableMedia = BitConverter.ToBoolean(descriptorB, 10),
|
||||
CommandQueueing = BitConverter.ToBoolean(descriptorB, 11),
|
||||
VendorIdOffset = BitConverter.ToInt32(descriptorB, 12),
|
||||
ProductIdOffset = BitConverter.ToInt32(descriptorB, 16),
|
||||
ProductRevisionOffset = BitConverter.ToInt32(descriptorB, 20),
|
||||
SerialNumberOffset = BitConverter.ToInt32(descriptorB, 24),
|
||||
BusType = (StorageBusType)BitConverter.ToUInt32(descriptorB, 28),
|
||||
RawPropertiesLength = BitConverter.ToUInt32(descriptorB, 32)
|
||||
SerialNumberOffset = BitConverter.ToInt32(descriptorB, 24),
|
||||
BusType = (StorageBusType)BitConverter.ToUInt32(descriptorB, 28),
|
||||
RawPropertiesLength = BitConverter.ToUInt32(descriptorB, 32)
|
||||
};
|
||||
|
||||
DeviceInfo info = new DeviceInfo {Path = physId, Bus = descriptor.BusType.ToString()};
|
||||
@@ -173,7 +173,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
if(pieces.Length > 1)
|
||||
{
|
||||
info.Vendor = pieces[0];
|
||||
info.Model = info.Model.Substring(pieces[0].Length + 1);
|
||||
info.Model = info.Model.Substring(pieces[0].Length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,26 +41,28 @@ namespace DiscImageChef.Devices.Windows
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct ScsiPassThroughDirect
|
||||
{
|
||||
public ushort Length;
|
||||
public byte ScsiStatus;
|
||||
public byte PathId;
|
||||
public byte TargetId;
|
||||
public byte Lun;
|
||||
public byte CdbLength;
|
||||
public byte SenseInfoLength;
|
||||
public ushort Length;
|
||||
public byte ScsiStatus;
|
||||
public byte PathId;
|
||||
public byte TargetId;
|
||||
public byte Lun;
|
||||
public byte CdbLength;
|
||||
public byte SenseInfoLength;
|
||||
[MarshalAs(UnmanagedType.U1)] public ScsiIoctlDirection DataIn;
|
||||
public uint DataTransferLength;
|
||||
public uint TimeOutValue;
|
||||
public IntPtr DataBuffer;
|
||||
public uint SenseInfoOffset;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] Cdb;
|
||||
public uint DataTransferLength;
|
||||
public uint TimeOutValue;
|
||||
public IntPtr DataBuffer;
|
||||
public uint SenseInfoOffset;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||
public byte[] Cdb;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct ScsiPassThroughDirectAndSenseBuffer
|
||||
{
|
||||
public ScsiPassThroughDirect sptd;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] SenseBuf;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||
public byte[] SenseBuf;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -122,8 +124,9 @@ namespace DiscImageChef.Devices.Windows
|
||||
struct AtaPassThroughDirectWithBuffer
|
||||
{
|
||||
public AtaPassThroughDirect aptd;
|
||||
public uint filler;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64 * 512)] public byte[] dataBuffer;
|
||||
public uint filler;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64 * 512)]
|
||||
public byte[] dataBuffer;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
@@ -151,8 +154,9 @@ namespace DiscImageChef.Devices.Windows
|
||||
struct StoragePropertyQuery
|
||||
{
|
||||
[MarshalAs(UnmanagedType.U4)] public StoragePropertyId PropertyId;
|
||||
[MarshalAs(UnmanagedType.U4)] public StorageQueryType QueryType;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public byte[] AdditionalParameters;
|
||||
[MarshalAs(UnmanagedType.U4)] public StorageQueryType QueryType;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
|
||||
public byte[] AdditionalParameters;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -166,19 +170,19 @@ namespace DiscImageChef.Devices.Windows
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct StorageDeviceDescriptor
|
||||
{
|
||||
public uint Version;
|
||||
public uint Size;
|
||||
public byte DeviceType;
|
||||
public byte DeviceTypeModifier;
|
||||
[MarshalAs(UnmanagedType.U1)] public bool RemovableMedia;
|
||||
[MarshalAs(UnmanagedType.U1)] public bool CommandQueueing;
|
||||
public int VendorIdOffset;
|
||||
public int ProductIdOffset;
|
||||
public int ProductRevisionOffset;
|
||||
public int SerialNumberOffset;
|
||||
public StorageBusType BusType;
|
||||
public uint RawPropertiesLength;
|
||||
public byte[] RawDeviceProperties;
|
||||
public uint Version;
|
||||
public uint Size;
|
||||
public byte DeviceType;
|
||||
public byte DeviceTypeModifier;
|
||||
[MarshalAs(UnmanagedType.U1)] public bool RemovableMedia;
|
||||
[MarshalAs(UnmanagedType.U1)] public bool CommandQueueing;
|
||||
public int VendorIdOffset;
|
||||
public int ProductIdOffset;
|
||||
public int ProductRevisionOffset;
|
||||
public int SerialNumberOffset;
|
||||
public StorageBusType BusType;
|
||||
public uint RawPropertiesLength;
|
||||
public byte[] RawDeviceProperties;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -195,7 +199,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <summary>
|
||||
/// Data buffer
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] public byte[] DataBuffer;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
|
||||
public byte[] DataBuffer;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -211,9 +216,9 @@ namespace DiscImageChef.Devices.Windows
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct DeviceInfoData
|
||||
{
|
||||
public int cbSize;
|
||||
public Guid classGuid;
|
||||
public uint devInst;
|
||||
public int cbSize;
|
||||
public Guid classGuid;
|
||||
public uint devInst;
|
||||
public IntPtr reserved;
|
||||
}
|
||||
|
||||
@@ -221,18 +226,18 @@ namespace DiscImageChef.Devices.Windows
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct DeviceInterfaceData
|
||||
{
|
||||
public int cbSize;
|
||||
public int cbSize;
|
||||
public Guid interfaceClassGuid;
|
||||
public uint flags;
|
||||
IntPtr reserved;
|
||||
IntPtr reserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct UsbSetupPacket
|
||||
{
|
||||
public byte bmRequest;
|
||||
public byte bRequest;
|
||||
public byte bmRequest;
|
||||
public byte bRequest;
|
||||
public short wValue;
|
||||
public short wIndex;
|
||||
public short wLength;
|
||||
@@ -242,7 +247,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct UsbDescriptorRequest
|
||||
{
|
||||
public int ConnectionIndex;
|
||||
public int ConnectionIndex;
|
||||
public UsbSetupPacket SetupPacket;
|
||||
//public byte[] Data;
|
||||
}
|
||||
@@ -253,28 +258,28 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
public ushort size;
|
||||
public ushort reserved;
|
||||
public Guid protocolGuid;
|
||||
public Guid protocolGuid;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
struct SffdiskDeviceCommandData
|
||||
{
|
||||
public ushort size;
|
||||
public ushort reserved;
|
||||
public ushort size;
|
||||
public ushort reserved;
|
||||
public SffdiskDcmd command;
|
||||
public ushort protocolArgumentSize;
|
||||
public uint deviceDataBufferSize;
|
||||
public uint information;
|
||||
public ushort protocolArgumentSize;
|
||||
public uint deviceDataBufferSize;
|
||||
public uint information;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct SdCmdDescriptor
|
||||
{
|
||||
public byte commandCode;
|
||||
public SdCommandClass cmdClass;
|
||||
public byte commandCode;
|
||||
public SdCommandClass cmdClass;
|
||||
public SdTransferDirection transferDirection;
|
||||
public SdTransferType transferType;
|
||||
public SdResponseType responseType;
|
||||
public SdTransferType transferType;
|
||||
public SdResponseType responseType;
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
static IEnumerable<UsbController> GetHostControllers()
|
||||
{
|
||||
List<UsbController> hostList = new List<UsbController>();
|
||||
Guid hostGuid = new Guid(GUID_DEVINTERFACE_HUBCONTROLLER);
|
||||
Guid hostGuid = new Guid(GUID_DEVINTERFACE_HUBCONTROLLER);
|
||||
|
||||
// We start at the "root" of the device tree and look for all
|
||||
// devices that match the interface GUID of a Hub Controller
|
||||
@@ -61,8 +61,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
if(h == INVALID_HANDLE_VALUE) return new ReadOnlyCollection<UsbController>(hostList);
|
||||
|
||||
IntPtr ptrBuf = Marshal.AllocHGlobal(BUFFER_SIZE);
|
||||
bool success;
|
||||
int i = 0;
|
||||
bool success;
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
UsbController host = new UsbController {ControllerIndex = i};
|
||||
@@ -85,25 +85,27 @@ namespace DiscImageChef.Devices.Windows
|
||||
// trust me :)
|
||||
|
||||
// now we can get some more detailed information
|
||||
int nRequiredSize = 0;
|
||||
const int N_BYTES = BUFFER_SIZE;
|
||||
int nRequiredSize = 0;
|
||||
const int N_BYTES = BUFFER_SIZE;
|
||||
if(SetupDiGetDeviceInterfaceDetail(h, ref dia, ref didd, N_BYTES, ref nRequiredSize, ref da))
|
||||
{
|
||||
host.ControllerDevicePath = didd.DevicePath;
|
||||
|
||||
// get the Device Description and DriverKeyName
|
||||
int requiredSize = 0;
|
||||
int regType = REG_SZ;
|
||||
int regType = REG_SZ;
|
||||
|
||||
if(SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DEVICEDESC, ref regType, ptrBuf,
|
||||
if(SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DEVICEDESC, ref regType, ptrBuf,
|
||||
BUFFER_SIZE, ref requiredSize))
|
||||
host.ControllerDeviceDesc = Marshal.PtrToStringAuto(ptrBuf);
|
||||
if(SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DRIVER, ref regType, ptrBuf, BUFFER_SIZE,
|
||||
ref requiredSize))
|
||||
host.ControllerDriverKeyName = Marshal.PtrToStringAuto(ptrBuf);
|
||||
}
|
||||
|
||||
hostList.Add(host);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
while(success);
|
||||
@@ -122,7 +124,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <returns>USB device description</returns>
|
||||
static string GetDescriptionByKeyName(string driverKeyName)
|
||||
{
|
||||
string ans = "";
|
||||
string ans = "";
|
||||
const string DEV_ENUM = REGSTR_KEY_USB;
|
||||
|
||||
// Use the "enumerator form" of the SetupDiGetClassDevs API
|
||||
@@ -133,7 +135,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
IntPtr ptrBuf = Marshal.AllocHGlobal(BUFFER_SIZE);
|
||||
|
||||
bool success;
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
// create a Device Interface Data structure
|
||||
@@ -144,9 +146,9 @@ namespace DiscImageChef.Devices.Windows
|
||||
success = SetupDiEnumDeviceInfo(h, i, ref da);
|
||||
if(success)
|
||||
{
|
||||
int requiredSize = 0;
|
||||
int regType = REG_SZ;
|
||||
string keyName = "";
|
||||
int requiredSize = 0;
|
||||
int regType = REG_SZ;
|
||||
string keyName = "";
|
||||
|
||||
if(SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DRIVER, ref regType, ptrBuf, BUFFER_SIZE,
|
||||
ref requiredSize)) keyName = Marshal.PtrToStringAuto(ptrBuf);
|
||||
@@ -154,7 +156,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
// is it a match?
|
||||
if(keyName == driverKeyName)
|
||||
{
|
||||
if(SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DEVICEDESC, ref regType, ptrBuf,
|
||||
if(SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DEVICEDESC, ref regType, ptrBuf,
|
||||
BUFFER_SIZE, ref requiredSize))
|
||||
ans = Marshal.PtrToStringAuto(ptrBuf);
|
||||
break;
|
||||
@@ -178,7 +180,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <returns>Device instance ID</returns>
|
||||
static string GetInstanceIdByKeyName(string driverKeyName)
|
||||
{
|
||||
string ans = "";
|
||||
string ans = "";
|
||||
const string DEV_ENUM = REGSTR_KEY_USB;
|
||||
|
||||
// Use the "enumerator form" of the SetupDiGetClassDevs API
|
||||
@@ -189,7 +191,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
IntPtr ptrBuf = Marshal.AllocHGlobal(BUFFER_SIZE);
|
||||
|
||||
bool success;
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
// create a Device Interface Data structure
|
||||
@@ -201,7 +203,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
if(success)
|
||||
{
|
||||
int requiredSize = 0;
|
||||
int regType = REG_SZ;
|
||||
int regType = REG_SZ;
|
||||
|
||||
string keyName = "";
|
||||
if(SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DRIVER, ref regType, ptrBuf, BUFFER_SIZE,
|
||||
@@ -210,8 +212,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
// is it a match?
|
||||
if(keyName == driverKeyName)
|
||||
{
|
||||
const int N_BYTES = BUFFER_SIZE;
|
||||
StringBuilder sb = new StringBuilder(N_BYTES);
|
||||
const int N_BYTES = BUFFER_SIZE;
|
||||
StringBuilder sb = new StringBuilder(N_BYTES);
|
||||
SetupDiGetDeviceInstanceId(h, ref da, sb, N_BYTES, out requiredSize);
|
||||
ans = sb.ToString();
|
||||
break;
|
||||
@@ -234,16 +236,16 @@ namespace DiscImageChef.Devices.Windows
|
||||
class UsbController
|
||||
{
|
||||
internal string ControllerDriverKeyName, ControllerDevicePath, ControllerDeviceDesc;
|
||||
internal int ControllerIndex;
|
||||
internal int ControllerIndex;
|
||||
|
||||
/// <summary>
|
||||
/// A simple default constructor
|
||||
/// </summary>
|
||||
internal UsbController()
|
||||
{
|
||||
ControllerIndex = 0;
|
||||
ControllerDevicePath = "";
|
||||
ControllerDeviceDesc = "";
|
||||
ControllerIndex = 0;
|
||||
ControllerDevicePath = "";
|
||||
ControllerDeviceDesc = "";
|
||||
ControllerDriverKeyName = "";
|
||||
}
|
||||
|
||||
@@ -273,15 +275,15 @@ namespace DiscImageChef.Devices.Windows
|
||||
IntPtr.Zero);
|
||||
if(h == INVALID_HANDLE_VALUE) return root;
|
||||
|
||||
UsbRootHubName hubName = new UsbRootHubName();
|
||||
int nBytes = Marshal.SizeOf(hubName);
|
||||
IntPtr ptrHubName = Marshal.AllocHGlobal(nBytes);
|
||||
UsbRootHubName hubName = new UsbRootHubName();
|
||||
int nBytes = Marshal.SizeOf(hubName);
|
||||
IntPtr ptrHubName = Marshal.AllocHGlobal(nBytes);
|
||||
|
||||
// get the Hub Name
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_ROOT_HUB_NAME, ptrHubName, nBytes, ptrHubName, nBytes, out _,
|
||||
IntPtr.Zero))
|
||||
{
|
||||
hubName = (UsbRootHubName)Marshal.PtrToStructure(ptrHubName, typeof(UsbRootHubName));
|
||||
hubName = (UsbRootHubName)Marshal.PtrToStructure(ptrHubName, typeof(UsbRootHubName));
|
||||
root.HubDevicePath = @"\\.\" + hubName.RootHubName;
|
||||
}
|
||||
|
||||
@@ -298,13 +300,15 @@ namespace DiscImageChef.Devices.Windows
|
||||
Marshal.StructureToPtr(nodeInfo, ptrNodeInfo, true);
|
||||
|
||||
// get the Hub Information
|
||||
if(DeviceIoControl(h2, IOCTL_USB_GET_NODE_INFORMATION, ptrNodeInfo, nBytes, ptrNodeInfo, nBytes,
|
||||
if(DeviceIoControl(h2, IOCTL_USB_GET_NODE_INFORMATION, ptrNodeInfo, nBytes, ptrNodeInfo, nBytes,
|
||||
out _, IntPtr.Zero))
|
||||
{
|
||||
nodeInfo = (UsbNodeInformation)Marshal.PtrToStructure(ptrNodeInfo, typeof(UsbNodeInformation));
|
||||
nodeInfo =
|
||||
(UsbNodeInformation)Marshal.PtrToStructure(ptrNodeInfo, typeof(UsbNodeInformation));
|
||||
root.HubIsBusPowered = Convert.ToBoolean(nodeInfo.HubInformation.HubIsBusPowered);
|
||||
root.HubPortCount = nodeInfo.HubInformation.HubDescriptor.bNumberOfPorts;
|
||||
root.HubPortCount = nodeInfo.HubInformation.HubDescriptor.bNumberOfPorts;
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(ptrNodeInfo);
|
||||
CloseHandle(h2);
|
||||
}
|
||||
@@ -318,24 +322,24 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// <summary>The Hub class</summary>
|
||||
internal class UsbHub
|
||||
{
|
||||
internal string HubDriverKey, HubDevicePath, HubDeviceDesc;
|
||||
internal bool HubIsBusPowered, HubIsRootHub;
|
||||
internal string HubDriverKey, HubDevicePath, HubDeviceDesc;
|
||||
internal bool HubIsBusPowered, HubIsRootHub;
|
||||
internal string HubManufacturer, HubProduct, HubSerialNumber, HubInstanceId;
|
||||
internal int HubPortCount;
|
||||
internal int HubPortCount;
|
||||
|
||||
/// <summary>a simple default constructor</summary>
|
||||
internal UsbHub()
|
||||
{
|
||||
HubPortCount = 0;
|
||||
HubDevicePath = "";
|
||||
HubDeviceDesc = "";
|
||||
HubDriverKey = "";
|
||||
HubPortCount = 0;
|
||||
HubDevicePath = "";
|
||||
HubDeviceDesc = "";
|
||||
HubDriverKey = "";
|
||||
HubIsBusPowered = false;
|
||||
HubIsRootHub = false;
|
||||
HubIsRootHub = false;
|
||||
HubManufacturer = "";
|
||||
HubProduct = "";
|
||||
HubProduct = "";
|
||||
HubSerialNumber = "";
|
||||
HubInstanceId = "";
|
||||
HubInstanceId = "";
|
||||
}
|
||||
|
||||
/// <summary>return Port Count</summary>
|
||||
@@ -381,7 +385,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
IntPtr.Zero);
|
||||
if(h == INVALID_HANDLE_VALUE) return new ReadOnlyCollection<UsbPort>(portList);
|
||||
|
||||
int nBytes = Marshal.SizeOf(typeof(UsbNodeConnectionInformationEx));
|
||||
int nBytes = Marshal.SizeOf(typeof(UsbNodeConnectionInformationEx));
|
||||
IntPtr ptrNodeConnection = Marshal.AllocHGlobal(nBytes);
|
||||
|
||||
// loop thru all of the ports on the hub
|
||||
@@ -392,8 +396,10 @@ namespace DiscImageChef.Devices.Windows
|
||||
new UsbNodeConnectionInformationEx {ConnectionIndex = i};
|
||||
Marshal.StructureToPtr(nodeConnection, ptrNodeConnection, true);
|
||||
|
||||
if(!DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ptrNodeConnection, nBytes,
|
||||
ptrNodeConnection, nBytes, out _, IntPtr.Zero)) continue;
|
||||
if(!DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
|
||||
ptrNodeConnection, nBytes,
|
||||
ptrNodeConnection, nBytes, out _,
|
||||
IntPtr.Zero)) continue;
|
||||
|
||||
nodeConnection =
|
||||
(UsbNodeConnectionInformationEx)Marshal.PtrToStructure(ptrNodeConnection,
|
||||
@@ -402,13 +408,13 @@ namespace DiscImageChef.Devices.Windows
|
||||
// load up the USBPort class
|
||||
UsbPort port = new UsbPort
|
||||
{
|
||||
PortPortNumber = i,
|
||||
PortPortNumber = i,
|
||||
PortHubDevicePath = HubDevicePath,
|
||||
PortStatus = ((UsbConnectionStatus)nodeConnection.ConnectionStatus).ToString(),
|
||||
PortSpeed = ((UsbDeviceSpeed)nodeConnection.Speed).ToString(),
|
||||
PortStatus = ((UsbConnectionStatus)nodeConnection.ConnectionStatus).ToString(),
|
||||
PortSpeed = ((UsbDeviceSpeed)nodeConnection.Speed).ToString(),
|
||||
PortIsDeviceConnected =
|
||||
nodeConnection.ConnectionStatus == (int)UsbConnectionStatus.DeviceConnected,
|
||||
PortIsHub = Convert.ToBoolean(nodeConnection.DeviceIsHub),
|
||||
PortIsHub = Convert.ToBoolean(nodeConnection.DeviceIsHub),
|
||||
PortDeviceDescriptor = nodeConnection.DeviceDescriptor
|
||||
};
|
||||
|
||||
@@ -429,18 +435,18 @@ namespace DiscImageChef.Devices.Windows
|
||||
internal class UsbPort
|
||||
{
|
||||
internal UsbDeviceDescriptor PortDeviceDescriptor;
|
||||
internal bool PortIsHub, PortIsDeviceConnected;
|
||||
internal int PortPortNumber;
|
||||
internal string PortStatus, PortHubDevicePath, PortSpeed;
|
||||
internal bool PortIsHub, PortIsDeviceConnected;
|
||||
internal int PortPortNumber;
|
||||
internal string PortStatus, PortHubDevicePath, PortSpeed;
|
||||
|
||||
/// <summary>a simple default constructor</summary>
|
||||
internal UsbPort()
|
||||
{
|
||||
PortPortNumber = 0;
|
||||
PortStatus = "";
|
||||
PortHubDevicePath = "";
|
||||
PortSpeed = "";
|
||||
PortIsHub = false;
|
||||
PortPortNumber = 0;
|
||||
PortStatus = "";
|
||||
PortHubDevicePath = "";
|
||||
PortSpeed = "";
|
||||
PortIsHub = false;
|
||||
PortIsDeviceConnected = false;
|
||||
}
|
||||
|
||||
@@ -474,9 +480,9 @@ namespace DiscImageChef.Devices.Windows
|
||||
// Ya know, I've given some thought about making Device a derived class...
|
||||
UsbDevice device = new UsbDevice
|
||||
{
|
||||
DevicePortNumber = PortPortNumber,
|
||||
DevicePortNumber = PortPortNumber,
|
||||
DeviceHubDevicePath = PortHubDevicePath,
|
||||
DeviceDescriptor = PortDeviceDescriptor
|
||||
DeviceDescriptor = PortDeviceDescriptor
|
||||
};
|
||||
|
||||
// Open a handle to the Hub device
|
||||
@@ -512,7 +518,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
Marshal.StructureToPtr(request, ptrRequest, true);
|
||||
|
||||
// Use an IOCTL call to request the String Descriptor
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest,
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes,
|
||||
ptrRequest,
|
||||
nBytes, out nBytesReturned, IntPtr.Zero))
|
||||
{
|
||||
// The location of the string descriptor is immediately after
|
||||
@@ -524,8 +531,10 @@ namespace DiscImageChef.Devices.Windows
|
||||
(UsbStringDescriptor)Marshal.PtrToStructure(ptrStringDesc, typeof(UsbStringDescriptor));
|
||||
device.DeviceManufacturer = stringDesc.bString;
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(ptrRequest);
|
||||
}
|
||||
|
||||
if(PortDeviceDescriptor.iProduct > 0)
|
||||
{
|
||||
// build a request for string descriptor
|
||||
@@ -545,7 +554,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
Marshal.StructureToPtr(request, ptrRequest, true);
|
||||
|
||||
// Use an IOCTL call to request the String Descriptor
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest,
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes,
|
||||
ptrRequest,
|
||||
nBytes, out nBytesReturned, IntPtr.Zero))
|
||||
{
|
||||
// the location of the string descriptor is immediately after the Request structure
|
||||
@@ -554,8 +564,10 @@ namespace DiscImageChef.Devices.Windows
|
||||
(UsbStringDescriptor)Marshal.PtrToStructure(ptrStringDesc, typeof(UsbStringDescriptor));
|
||||
device.DeviceProduct = stringDesc.bString;
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(ptrRequest);
|
||||
}
|
||||
|
||||
if(PortDeviceDescriptor.iSerialNumber > 0)
|
||||
{
|
||||
// build a request for string descriptor
|
||||
@@ -575,7 +587,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
Marshal.StructureToPtr(request, ptrRequest, true);
|
||||
|
||||
// Use an IOCTL call to request the String Descriptor
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest,
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes,
|
||||
ptrRequest,
|
||||
nBytes, out nBytesReturned, IntPtr.Zero))
|
||||
{
|
||||
// the location of the string descriptor is immediately after the Request structure
|
||||
@@ -584,6 +597,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
(UsbStringDescriptor)Marshal.PtrToStructure(ptrStringDesc, typeof(UsbStringDescriptor));
|
||||
device.DeviceSerialNumber = stringDesc.bString;
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(ptrRequest);
|
||||
}
|
||||
|
||||
@@ -591,7 +605,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
UsbDescriptorRequest dcrRequest = new UsbDescriptorRequest
|
||||
{
|
||||
ConnectionIndex = PortPortNumber,
|
||||
SetupPacket = {wIndex = 0, wValue = USB_CONFIGURATION_DESCRIPTOR_TYPE << 8}
|
||||
SetupPacket = {wIndex = 0, wValue = USB_CONFIGURATION_DESCRIPTOR_TYPE << 8}
|
||||
};
|
||||
dcrRequest.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(dcrRequest));
|
||||
// Geez, I wish C# had a Marshal.MemSet() method
|
||||
@@ -599,13 +613,16 @@ namespace DiscImageChef.Devices.Windows
|
||||
Marshal.StructureToPtr(dcrRequest, dcrPtrRequest, true);
|
||||
|
||||
// Use an IOCTL call to request the String Descriptor
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, dcrPtrRequest, nBytes,
|
||||
dcrPtrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, dcrPtrRequest,
|
||||
nBytes,
|
||||
dcrPtrRequest, nBytes, out nBytesReturned,
|
||||
IntPtr.Zero))
|
||||
{
|
||||
IntPtr ptrStringDesc = IntPtr.Add(dcrPtrRequest, Marshal.SizeOf(dcrRequest));
|
||||
device.BinaryDeviceDescriptors = new byte[nBytesReturned];
|
||||
Marshal.Copy(ptrStringDesc, device.BinaryDeviceDescriptors, 0, nBytesReturned);
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(dcrPtrRequest);
|
||||
|
||||
// Get the Driver Key Name (usefull in locating a device)
|
||||
@@ -616,7 +633,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
Marshal.StructureToPtr(driverKey, ptrDriverKey, true);
|
||||
|
||||
// Use an IOCTL call to request the Driver Key Name
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ptrDriverKey, nBytes, ptrDriverKey,
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ptrDriverKey, nBytes,
|
||||
ptrDriverKey,
|
||||
nBytes, out nBytesReturned, IntPtr.Zero))
|
||||
{
|
||||
driverKey = (UsbNodeConnectionDriverkeyName)Marshal.PtrToStructure(ptrDriverKey,
|
||||
@@ -626,9 +644,10 @@ namespace DiscImageChef.Devices.Windows
|
||||
device.DeviceDriverKey = driverKey.DriverKeyName;
|
||||
|
||||
// use the DriverKeyName to get the Device Description and Instance ID
|
||||
device.DeviceName = GetDescriptionByKeyName(device.DeviceDriverKey);
|
||||
device.DeviceName = GetDescriptionByKeyName(device.DeviceDriverKey);
|
||||
device.DeviceInstanceId = GetInstanceIdByKeyName(device.DeviceDriverKey);
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(ptrDriverKey);
|
||||
CloseHandle(h);
|
||||
return device;
|
||||
@@ -644,21 +663,22 @@ namespace DiscImageChef.Devices.Windows
|
||||
|
||||
UsbHub hub = new UsbHub();
|
||||
IntPtr h, h2;
|
||||
hub.HubIsRootHub = false;
|
||||
hub.HubIsRootHub = false;
|
||||
hub.HubDeviceDesc = "External Hub";
|
||||
|
||||
// Open a handle to the Host Controller
|
||||
h = CreateFile(PortHubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0,
|
||||
IntPtr.Zero);
|
||||
if(h == INVALID_HANDLE_VALUE) return hub;
|
||||
|
||||
// Get the DevicePath for downstream hub
|
||||
UsbNodeConnectionName nodeName = new UsbNodeConnectionName {ConnectionIndex = PortPortNumber};
|
||||
int nBytes = Marshal.SizeOf(nodeName);
|
||||
IntPtr ptrNodeName = Marshal.AllocHGlobal(nBytes);
|
||||
UsbNodeConnectionName nodeName = new UsbNodeConnectionName {ConnectionIndex = PortPortNumber};
|
||||
int nBytes = Marshal.SizeOf(nodeName);
|
||||
IntPtr ptrNodeName = Marshal.AllocHGlobal(nBytes);
|
||||
Marshal.StructureToPtr(nodeName, ptrNodeName, true);
|
||||
|
||||
// Use an IOCTL call to request the Node Name
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_NAME, ptrNodeName, nBytes, ptrNodeName, nBytes,
|
||||
if(DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_NAME, ptrNodeName, nBytes, ptrNodeName, nBytes,
|
||||
out _, IntPtr.Zero))
|
||||
{
|
||||
nodeName = (UsbNodeConnectionName)Marshal.PtrToStructure(ptrNodeName,
|
||||
@@ -677,13 +697,15 @@ namespace DiscImageChef.Devices.Windows
|
||||
Marshal.StructureToPtr(nodeInfo, ptrNodeInfo, true);
|
||||
|
||||
// get the Hub Information
|
||||
if(DeviceIoControl(h2, IOCTL_USB_GET_NODE_INFORMATION, ptrNodeInfo, nBytes, ptrNodeInfo, nBytes,
|
||||
if(DeviceIoControl(h2, IOCTL_USB_GET_NODE_INFORMATION, ptrNodeInfo, nBytes, ptrNodeInfo, nBytes,
|
||||
out _, IntPtr.Zero))
|
||||
{
|
||||
nodeInfo = (UsbNodeInformation)Marshal.PtrToStructure(ptrNodeInfo, typeof(UsbNodeInformation));
|
||||
nodeInfo =
|
||||
(UsbNodeInformation)Marshal.PtrToStructure(ptrNodeInfo, typeof(UsbNodeInformation));
|
||||
hub.HubIsBusPowered = Convert.ToBoolean(nodeInfo.HubInformation.HubIsBusPowered);
|
||||
hub.HubPortCount = nodeInfo.HubInformation.HubDescriptor.bNumberOfPorts;
|
||||
hub.HubPortCount = nodeInfo.HubInformation.HubDescriptor.bNumberOfPorts;
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(ptrNodeInfo);
|
||||
CloseHandle(h2);
|
||||
}
|
||||
@@ -691,11 +713,11 @@ namespace DiscImageChef.Devices.Windows
|
||||
// Fill in the missing Manufacture, Product, and SerialNumber values
|
||||
// values by just creating a Device instance and copying the values
|
||||
UsbDevice device = GetDevice();
|
||||
hub.HubInstanceId = device.DeviceInstanceId;
|
||||
hub.HubInstanceId = device.DeviceInstanceId;
|
||||
hub.HubManufacturer = device.Manufacturer;
|
||||
hub.HubProduct = device.Product;
|
||||
hub.HubProduct = device.Product;
|
||||
hub.HubSerialNumber = device.SerialNumber;
|
||||
hub.HubDriverKey = device.DriverKey;
|
||||
hub.HubDriverKey = device.DriverKey;
|
||||
|
||||
Marshal.FreeHGlobal(ptrNodeName);
|
||||
CloseHandle(h);
|
||||
@@ -708,23 +730,23 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// </summary>
|
||||
internal class UsbDevice
|
||||
{
|
||||
internal byte[] BinaryDeviceDescriptors;
|
||||
internal byte[] BinaryDeviceDescriptors;
|
||||
internal UsbDeviceDescriptor DeviceDescriptor;
|
||||
internal string DeviceDriverKey, DeviceHubDevicePath, DeviceInstanceId, DeviceName;
|
||||
internal string DeviceManufacturer, DeviceProduct, DeviceSerialNumber;
|
||||
internal int DevicePortNumber;
|
||||
internal string DeviceDriverKey, DeviceHubDevicePath, DeviceInstanceId, DeviceName;
|
||||
internal string DeviceManufacturer, DeviceProduct, DeviceSerialNumber;
|
||||
internal int DevicePortNumber;
|
||||
|
||||
/// <summary>a simple default constructor</summary>
|
||||
internal UsbDevice()
|
||||
{
|
||||
DevicePortNumber = 0;
|
||||
DeviceHubDevicePath = "";
|
||||
DeviceDriverKey = "";
|
||||
DeviceManufacturer = "";
|
||||
DeviceProduct = "Unknown USB Device";
|
||||
DeviceSerialNumber = "";
|
||||
DeviceName = "";
|
||||
DeviceInstanceId = "";
|
||||
DevicePortNumber = 0;
|
||||
DeviceHubDevicePath = "";
|
||||
DeviceDriverKey = "";
|
||||
DeviceManufacturer = "";
|
||||
DeviceProduct = "Unknown USB Device";
|
||||
DeviceSerialNumber = "";
|
||||
DeviceName = "";
|
||||
DeviceInstanceId = "";
|
||||
BinaryDeviceDescriptors = null;
|
||||
}
|
||||
|
||||
@@ -755,35 +777,35 @@ namespace DiscImageChef.Devices.Windows
|
||||
#region "API Region"
|
||||
// ********************** Constants ************************
|
||||
|
||||
const int GENERIC_WRITE = 0x40000000;
|
||||
const int FILE_SHARE_READ = 0x1;
|
||||
const int FILE_SHARE_WRITE = 0x2;
|
||||
const int OPEN_EXISTING = 0x3;
|
||||
const int GENERIC_WRITE = 0x40000000;
|
||||
const int FILE_SHARE_READ = 0x1;
|
||||
const int FILE_SHARE_WRITE = 0x2;
|
||||
const int OPEN_EXISTING = 0x3;
|
||||
static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
|
||||
|
||||
const int IOCTL_GET_HCD_DRIVERKEY_NAME = 0x220424;
|
||||
const int IOCTL_USB_GET_ROOT_HUB_NAME = 0x220408;
|
||||
const int IOCTL_USB_GET_NODE_INFORMATION = 0x220408; // same as above... strange, eh?
|
||||
const int IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX = 0x220448;
|
||||
const int IOCTL_GET_HCD_DRIVERKEY_NAME = 0x220424;
|
||||
const int IOCTL_USB_GET_ROOT_HUB_NAME = 0x220408;
|
||||
const int IOCTL_USB_GET_NODE_INFORMATION = 0x220408; // same as above... strange, eh?
|
||||
const int IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX = 0x220448;
|
||||
const int IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION = 0x220410;
|
||||
const int IOCTL_USB_GET_NODE_CONNECTION_NAME = 0x220414;
|
||||
const int IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME = 0x220420;
|
||||
const int IOCTL_USB_GET_NODE_CONNECTION_NAME = 0x220414;
|
||||
const int IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME = 0x220420;
|
||||
|
||||
const int USB_DEVICE_DESCRIPTOR_TYPE = 0x1;
|
||||
const int USB_DEVICE_DESCRIPTOR_TYPE = 0x1;
|
||||
const int USB_CONFIGURATION_DESCRIPTOR_TYPE = 0x2;
|
||||
const int USB_STRING_DESCRIPTOR_TYPE = 0x3;
|
||||
const int USB_STRING_DESCRIPTOR_TYPE = 0x3;
|
||||
|
||||
const int BUFFER_SIZE = 2048;
|
||||
const int BUFFER_SIZE = 2048;
|
||||
const int MAXIMUM_USB_STRING_LENGTH = 255;
|
||||
|
||||
const string GUID_DEVINTERFACE_HUBCONTROLLER = "3abf6f2d-71c4-462a-8a92-1e6861e6af27";
|
||||
const string REGSTR_KEY_USB = "USB";
|
||||
const int DIGCF_PRESENT = 0x2;
|
||||
const int DIGCF_ALLCLASSES = 0x4;
|
||||
const int DIGCF_DEVICEINTERFACE = 0x10;
|
||||
const int SPDRP_DRIVER = 0x9;
|
||||
const int SPDRP_DEVICEDESC = 0x0;
|
||||
const int REG_SZ = 1;
|
||||
const string REGSTR_KEY_USB = "USB";
|
||||
const int DIGCF_PRESENT = 0x2;
|
||||
const int DIGCF_ALLCLASSES = 0x4;
|
||||
const int DIGCF_DEVICEINTERFACE = 0x10;
|
||||
const int SPDRP_DRIVER = 0x9;
|
||||
const int SPDRP_DEVICEDESC = 0x0;
|
||||
const int REG_SZ = 1;
|
||||
|
||||
// ********************** Enumerations ************************
|
||||
|
||||
@@ -818,8 +840,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct SpDevinfoData
|
||||
{
|
||||
internal int cbSize;
|
||||
internal Guid ClassGuid;
|
||||
internal int cbSize;
|
||||
internal Guid ClassGuid;
|
||||
internal IntPtr DevInst;
|
||||
internal IntPtr Reserved;
|
||||
}
|
||||
@@ -827,9 +849,9 @@ namespace DiscImageChef.Devices.Windows
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct SpDeviceInterfaceData
|
||||
{
|
||||
internal int cbSize;
|
||||
internal Guid InterfaceClassGuid;
|
||||
internal int Flags;
|
||||
internal int cbSize;
|
||||
internal Guid InterfaceClassGuid;
|
||||
internal int Flags;
|
||||
internal IntPtr Reserved;
|
||||
}
|
||||
|
||||
@@ -837,59 +859,63 @@ namespace DiscImageChef.Devices.Windows
|
||||
struct SpDeviceInterfaceDetailData
|
||||
{
|
||||
internal int cbSize;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)] internal string DevicePath;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
|
||||
internal string DevicePath;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
struct UsbHcdDriverkeyName
|
||||
{
|
||||
internal int ActualLength;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)] internal string DriverKeyName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
|
||||
internal string DriverKeyName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
struct UsbRootHubName
|
||||
{
|
||||
internal int ActualLength;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)] internal string RootHubName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
|
||||
internal string RootHubName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct UsbHubDescriptor
|
||||
{
|
||||
internal byte bDescriptorLength;
|
||||
internal byte bDescriptorType;
|
||||
internal byte bNumberOfPorts;
|
||||
internal byte bDescriptorLength;
|
||||
internal byte bDescriptorType;
|
||||
internal byte bNumberOfPorts;
|
||||
internal short wHubCharacteristics;
|
||||
internal byte bPowerOnToPowerGood;
|
||||
internal byte bHubControlCurrent;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] internal byte[] bRemoveAndPowerMask;
|
||||
internal byte bPowerOnToPowerGood;
|
||||
internal byte bHubControlCurrent;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
|
||||
internal byte[] bRemoveAndPowerMask;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct UsbHubInformation
|
||||
{
|
||||
internal UsbHubDescriptor HubDescriptor;
|
||||
internal byte HubIsBusPowered;
|
||||
internal byte HubIsBusPowered;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct UsbNodeInformation
|
||||
{
|
||||
internal int NodeType;
|
||||
internal int NodeType;
|
||||
internal UsbHubInformation HubInformation; // Yeah, I'm assuming we'll just use the first form
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct UsbNodeConnectionInformationEx
|
||||
{
|
||||
internal int ConnectionIndex;
|
||||
internal int ConnectionIndex;
|
||||
internal UsbDeviceDescriptor DeviceDescriptor;
|
||||
internal byte CurrentConfigurationValue;
|
||||
internal byte Speed;
|
||||
internal byte DeviceIsHub;
|
||||
internal short DeviceAddress;
|
||||
internal int NumberOfOpenPipes;
|
||||
internal byte CurrentConfigurationValue;
|
||||
internal byte Speed;
|
||||
internal byte DeviceIsHub;
|
||||
internal short DeviceAddress;
|
||||
internal int NumberOfOpenPipes;
|
||||
|
||||
internal int ConnectionStatus;
|
||||
//internal IntPtr PipeList;
|
||||
@@ -899,20 +925,20 @@ namespace DiscImageChef.Devices.Windows
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
internal struct UsbDeviceDescriptor
|
||||
{
|
||||
internal byte bLength;
|
||||
internal byte bDescriptorType;
|
||||
internal byte bLength;
|
||||
internal byte bDescriptorType;
|
||||
internal short bcdUSB;
|
||||
internal byte bDeviceClass;
|
||||
internal byte bDeviceSubClass;
|
||||
internal byte bDeviceProtocol;
|
||||
internal byte bMaxPacketSize0;
|
||||
internal byte bDeviceClass;
|
||||
internal byte bDeviceSubClass;
|
||||
internal byte bDeviceProtocol;
|
||||
internal byte bMaxPacketSize0;
|
||||
internal short idVendor;
|
||||
internal short idProduct;
|
||||
internal short bcdDevice;
|
||||
internal byte iManufacturer;
|
||||
internal byte iProduct;
|
||||
internal byte iSerialNumber;
|
||||
internal byte bNumConfigurations;
|
||||
internal byte iManufacturer;
|
||||
internal byte iProduct;
|
||||
internal byte iSerialNumber;
|
||||
internal byte bNumConfigurations;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
@@ -920,14 +946,15 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
internal byte bLength;
|
||||
internal byte bDescriptorType;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXIMUM_USB_STRING_LENGTH)] internal string bString;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXIMUM_USB_STRING_LENGTH)]
|
||||
internal string bString;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct UsbSetupPacket
|
||||
{
|
||||
internal byte bmRequest;
|
||||
internal byte bRequest;
|
||||
internal byte bmRequest;
|
||||
internal byte bRequest;
|
||||
internal short wValue;
|
||||
internal short wIndex;
|
||||
internal short wLength;
|
||||
@@ -947,7 +974,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
internal int ConnectionIndex;
|
||||
internal int ActualLength;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)] internal string NodeName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
|
||||
internal string NodeName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
@@ -955,7 +983,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
{
|
||||
internal int ConnectionIndex;
|
||||
internal int ActualLength;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)] internal string DriverKeyName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
|
||||
internal string DriverKeyName;
|
||||
}
|
||||
|
||||
// ********************** API Definitions ************************
|
||||
@@ -968,44 +997,50 @@ namespace DiscImageChef.Devices.Windows
|
||||
static extern IntPtr SetupDiGetClassDevs(int classGuid, string enumerator, IntPtr hwndParent, int flags);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool SetupDiEnumDeviceInterfaces(IntPtr deviceInfoSet, IntPtr deviceInfoData,
|
||||
ref Guid interfaceClassGuid, int memberIndex,
|
||||
static extern bool SetupDiEnumDeviceInterfaces(IntPtr deviceInfoSet,
|
||||
IntPtr deviceInfoData,
|
||||
ref Guid interfaceClassGuid, int memberIndex,
|
||||
ref SpDeviceInterfaceData deviceInterfaceData);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr deviceInfoSet,
|
||||
ref SpDeviceInterfaceData deviceInterfaceData,
|
||||
static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr deviceInfoSet,
|
||||
ref SpDeviceInterfaceData deviceInterfaceData,
|
||||
ref SpDeviceInterfaceDetailData deviceInterfaceDetailData,
|
||||
int deviceInterfaceDetailDataSize, ref int requiredSize,
|
||||
int
|
||||
deviceInterfaceDetailDataSize, ref int requiredSize,
|
||||
ref SpDevinfoData deviceInfoData);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool SetupDiGetDeviceRegistryProperty(IntPtr deviceInfoSet, ref SpDevinfoData deviceInfoData,
|
||||
int iProperty, ref int propertyRegDataType,
|
||||
IntPtr propertyBuffer, int propertyBufferSize,
|
||||
static extern bool SetupDiGetDeviceRegistryProperty(IntPtr deviceInfoSet, ref SpDevinfoData deviceInfoData,
|
||||
int iProperty,
|
||||
ref int propertyRegDataType,
|
||||
IntPtr propertyBuffer,
|
||||
int propertyBufferSize,
|
||||
ref int requiredSize);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet, int memberIndex,
|
||||
static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet, int memberIndex,
|
||||
ref SpDevinfoData deviceInfoData);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true)]
|
||||
static extern bool SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool SetupDiGetDeviceInstanceId(IntPtr deviceInfoSet, ref SpDevinfoData deviceInfoData,
|
||||
StringBuilder deviceInstanceId, int deviceInstanceIdSize,
|
||||
out int requiredSize);
|
||||
static extern bool SetupDiGetDeviceInstanceId(IntPtr deviceInfoSet, ref SpDevinfoData deviceInfoData,
|
||||
StringBuilder deviceInstanceId,
|
||||
int deviceInstanceIdSize,
|
||||
out int requiredSize);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, IntPtr lpInBuffer, int nInBufferSize,
|
||||
static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, IntPtr lpInBuffer,
|
||||
int nInBufferSize,
|
||||
IntPtr lpOutBuffer, int nOutBufferSize, out int lpBytesReturned,
|
||||
IntPtr lpOverlapped);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
|
||||
IntPtr lpSecurityAttributes, int dwCreationDisposition,
|
||||
int dwFlagsAndAttributes, IntPtr hTemplateFile);
|
||||
static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
|
||||
IntPtr lpSecurityAttributes, int dwCreationDisposition,
|
||||
int dwFlagsAndAttributes, IntPtr hTemplateFile);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
@@ -47,10 +47,10 @@ namespace DiscImageChef.Devices.Windows
|
||||
/// </summary>
|
||||
static partial class Usb
|
||||
{
|
||||
const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080;
|
||||
internal const string GuidDevinterfaceDisk = "53f56307-b6bf-11d0-94f2-00a0c91efb8b";
|
||||
internal const string GuidDevinterfaceCdrom = "53f56308-b6bf-11d0-94f2-00a0c91efb8b";
|
||||
internal const string GuidDevinterfaceFloppy = "53f56311-b6bf-11d0-94f2-00a0c91efb8b";
|
||||
const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080;
|
||||
internal const string GuidDevinterfaceDisk = "53f56307-b6bf-11d0-94f2-00a0c91efb8b";
|
||||
internal const string GuidDevinterfaceCdrom = "53f56308-b6bf-11d0-94f2-00a0c91efb8b";
|
||||
internal const string GuidDevinterfaceFloppy = "53f56311-b6bf-11d0-94f2-00a0c91efb8b";
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all connected devices
|
||||
@@ -73,8 +73,12 @@ namespace DiscImageChef.Devices.Windows
|
||||
static void ListHub(UsbHub hub, ICollection<UsbDevice> devList)
|
||||
{
|
||||
foreach(UsbPort port in hub.GetPorts())
|
||||
if(port.IsHub) ListHub(port.GetHub(), devList);
|
||||
else { if(port.IsDeviceConnected) devList.Add(port.GetDevice()); }
|
||||
if(port.IsHub)
|
||||
ListHub(port.GetHub(), devList);
|
||||
else
|
||||
{
|
||||
if(port.IsDeviceConnected) devList.Add(port.GetDevice());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -104,7 +108,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
static void SearchHubDriverKeyName(UsbHub hub, ref UsbDevice foundDevice, string driverKeyName)
|
||||
{
|
||||
foreach(UsbPort port in hub.GetPorts())
|
||||
if(port.IsHub) SearchHubDriverKeyName(port.GetHub(), ref foundDevice, driverKeyName);
|
||||
if(port.IsHub)
|
||||
SearchHubDriverKeyName(port.GetHub(), ref foundDevice, driverKeyName);
|
||||
else
|
||||
{
|
||||
if(!port.IsDeviceConnected) continue;
|
||||
@@ -144,7 +149,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
static void SearchHubInstanceId(UsbHub hub, ref UsbDevice foundDevice, string instanceId)
|
||||
{
|
||||
foreach(UsbPort port in hub.GetPorts())
|
||||
if(port.IsHub) SearchHubInstanceId(port.GetHub(), ref foundDevice, instanceId);
|
||||
if(port.IsHub)
|
||||
SearchHubInstanceId(port.GetHub(), ref foundDevice, instanceId);
|
||||
else
|
||||
{
|
||||
if(!port.IsDeviceConnected) continue;
|
||||
@@ -202,7 +208,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
static UsbDevice FindDeviceNumber(int devNum, string deviceGuid)
|
||||
{
|
||||
UsbDevice foundDevice = null;
|
||||
string instanceId = "";
|
||||
string instanceId = "";
|
||||
|
||||
Guid diskGuid = new Guid(deviceGuid);
|
||||
|
||||
@@ -212,7 +218,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
if(h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
bool success;
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
// create a Device Interface Data structure
|
||||
@@ -232,8 +238,8 @@ namespace DiscImageChef.Devices.Windows
|
||||
new SpDeviceInterfaceDetailData {cbSize = 4 + Marshal.SystemDefaultCharSize}; // trust me :)
|
||||
|
||||
// now we can get some more detailed information
|
||||
int nRequiredSize = 0;
|
||||
const int N_BYTES = BUFFER_SIZE;
|
||||
int nRequiredSize = 0;
|
||||
const int N_BYTES = BUFFER_SIZE;
|
||||
if(SetupDiGetDeviceInterfaceDetail(h, ref dia, ref didd, N_BYTES, ref nRequiredSize, ref da))
|
||||
if(GetDeviceNumber(didd.DevicePath) == devNum)
|
||||
{
|
||||
@@ -251,6 +257,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
while(success);
|
||||
@@ -276,9 +283,9 @@ namespace DiscImageChef.Devices.Windows
|
||||
IntPtr h = CreateFile(devicePath.TrimEnd('\\'), 0, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
|
||||
if(h == INVALID_HANDLE_VALUE) return ans;
|
||||
|
||||
StorageDeviceNumber sdn = new StorageDeviceNumber();
|
||||
int nBytes = Marshal.SizeOf(sdn);
|
||||
IntPtr ptrSdn = Marshal.AllocHGlobal(nBytes);
|
||||
StorageDeviceNumber sdn = new StorageDeviceNumber();
|
||||
int nBytes = Marshal.SizeOf(sdn);
|
||||
IntPtr ptrSdn = Marshal.AllocHGlobal(nBytes);
|
||||
|
||||
if(DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, IntPtr.Zero, 0, ptrSdn, nBytes, out _, IntPtr.Zero))
|
||||
{
|
||||
@@ -287,6 +294,7 @@ namespace DiscImageChef.Devices.Windows
|
||||
// STORAGE_DEVICE_NUMBER into a single number
|
||||
ans = (sdn.DeviceType << 8) + sdn.DeviceNumber;
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(ptrSdn);
|
||||
CloseHandle(h);
|
||||
return ans;
|
||||
|
||||
Reference in New Issue
Block a user