Implemented reading SD/MMC using buffered OS calls.

This commit is contained in:
2020-12-12 22:48:03 +00:00
parent 04a2626125
commit c788a4ded5
12 changed files with 114 additions and 3 deletions

View File

@@ -550,7 +550,8 @@ namespace Aaru.Core.Devices.Dumping
error = _dev.ReadWithBlockCount(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, byteAddressed, error = _dev.ReadWithBlockCount(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, byteAddressed,
timeout, out duration); timeout, out duration);
else if(_useBufferedReads) else if(_useBufferedReads)
throw new NotImplementedException(); error = _dev.BufferedOsRead(out cmdBuf, (long)(i * blockSize), blockSize * blocksToRead,
out duration);
else else
error = _dev.ReadMultipleUsingSingle(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, error = _dev.ReadMultipleUsingSingle(out cmdBuf, out _, (uint)i, blockSize, blocksToRead,
byteAddressed, timeout, out duration); byteAddressed, timeout, out duration);

View File

@@ -253,7 +253,8 @@ namespace Aaru.Core.Devices.Scanning
error = _dev.ReadWithBlockCount(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, byteAddressed, error = _dev.ReadWithBlockCount(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, byteAddressed,
timeout, out duration); timeout, out duration);
else if(_useBufferedReads) else if(_useBufferedReads)
throw new NotImplementedException(); error = _dev.BufferedOsRead(out cmdBuf, (long)(i * blockSize), blockSize * blocksToRead,
out duration);
else else
error = _dev.ReadMultipleUsingSingle(out cmdBuf, out _, (uint)i, blockSize, blocksToRead, error = _dev.ReadMultipleUsingSingle(out cmdBuf, out _, (uint)i, blockSize, blocksToRead,
byteAddressed, timeout, out duration); byteAddressed, timeout, out duration);

View File

@@ -472,5 +472,18 @@ namespace Aaru.Devices
default: throw new InvalidOperationException($"Platform {ptId} not yet supported."); default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
} }
} }
internal static int BufferedOsRead(PlatformID ptId, object fd, out byte[] buffer, long offset, uint length,
out double duration)
{
switch(ptId)
{
case PlatformID.Win32NT:
return Windows.Command.BufferedOsRead((SafeFileHandle)fd, out buffer, offset, length, out duration);
case PlatformID.Linux:
return Linux.Command.BufferedOsRead((int)fd, out buffer, offset, length, out duration);
default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
}
}
} }
} }

View File

@@ -283,5 +283,18 @@ namespace Aaru.Devices
return Error; return Error;
} }
public bool BufferedOsRead(out byte[] buffer, long offset, uint length, out double duration)
{
if(!(_remote is null))
return _remote.BufferedOsRead(out buffer, offset, length, out duration);
int ret = Command.BufferedOsRead(PlatformId, FileHandle, out buffer, offset, length, out duration);
Error = ret != 0;
LastError = ret;
return Error;
}
} }
} }

View File

@@ -594,5 +594,30 @@ namespace Aaru.Devices.Linux
return Encoding.ASCII.GetString(resultString); return Encoding.ASCII.GetString(resultString);
} }
internal static int BufferedOsRead(int fd, out byte[] buffer, long offset, uint length, out double duration)
{
buffer = new byte[length];
DateTime start = DateTime.Now;
long sense = Extern.lseek(fd, offset, SeekWhence.Begin);
DateTime end = DateTime.Now;
if(sense < 0)
{
duration = (end - start).TotalMilliseconds;
return Marshal.GetLastWin32Error();
}
sense = DetectOS.Is64Bit ? Extern.read64(fd, buffer, length) : Extern.read(fd, buffer, (int)length);
end = DateTime.Now;
duration = (end - start).TotalMilliseconds;
return sense < 0 ? Marshal.GetLastWin32Error() : 0;
}
} }
} }

View File

@@ -124,4 +124,10 @@ namespace Aaru.Devices.Linux
DirectIo = 1, UnusedLunInhibit = 2, MmapIo = 4, DirectIo = 1, UnusedLunInhibit = 2, MmapIo = 4,
NoDxfer = 0x10000, QAtTail = 0x10, QAtHead = 0x20 NoDxfer = 0x10000, QAtTail = 0x10, QAtHead = 0x20
} }
internal enum SeekWhence
{
Begin = 0, Current = 1, End = 2,
Data = 3, Hole = 4
}
} }

View File

@@ -71,5 +71,14 @@ namespace Aaru.Devices.Linux
[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)] [DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
internal static extern int ioctlMmcMulti(int fd, LinuxIoctl request, IntPtr value); internal static extern int ioctlMmcMulti(int fd, LinuxIoctl request, IntPtr value);
[DllImport("libc", SetLastError = true)]
internal static extern long lseek(int fd, long offset, SeekWhence whence);
[DllImport("libc", SetLastError = true)]
internal static extern int read(int fd, byte[] buf, int count);
[DllImport("libc", EntryPoint = "read", SetLastError = true)]
internal static extern long read64(int fd, byte[] buf, long count);
} }
} }

View File

@@ -1445,5 +1445,8 @@ namespace Aaru.Devices.Remote
} }
public bool ReOpen() => throw new NotImplementedException(); public bool ReOpen() => throw new NotImplementedException();
public bool BufferedOsRead(out byte[] buffer, long offset, uint length, out double duration) =>
throw new NotImplementedException();
} }
} }

View File

@@ -633,5 +633,32 @@ namespace Aaru.Devices.Windows
return ((SafeFileHandle)newFd).IsInvalid ? Marshal.GetLastWin32Error() : 0; return ((SafeFileHandle)newFd).IsInvalid ? Marshal.GetLastWin32Error() : 0;
} }
internal static int BufferedOsRead(SafeFileHandle fd, out byte[] buffer, long offset, uint length,
out double duration)
{
buffer = new byte[length];
DateTime start = DateTime.Now;
bool sense = !Extern.SetFilePointerEx(fd, offset, out _, MoveMethod.Begin);
;
DateTime end = DateTime.Now;
if(sense)
{
duration = (end - start).TotalMilliseconds;
return Marshal.GetLastWin32Error();
}
sense = !Extern.ReadFile(fd, buffer, length, out _, IntPtr.Zero);
end = DateTime.Now;
duration = (end - start).TotalMilliseconds;
return sense ? Marshal.GetLastWin32Error() : 0;
}
} }
} }

View File

@@ -356,4 +356,9 @@ namespace Aaru.Devices.Windows
public static Guid GuidDevinterfaceDisk = public static Guid GuidDevinterfaceDisk =
new Guid(0x53F56307, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B); new Guid(0x53F56307, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B);
} }
internal enum MoveMethod : uint
{
Begin = 0, Current = 1, End = 2
}
} }

View File

@@ -112,5 +112,13 @@ namespace Aaru.Devices.Windows
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern bool CloseHandle(SafeFileHandle hDevice); internal static extern bool CloseHandle(SafeFileHandle hDevice);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove,
out long lpNewFilePointer, MoveMethod dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool ReadFile(SafeFileHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
} }
} }

View File

@@ -810,7 +810,7 @@ namespace Aaru.Gui.ViewModels.Windows
Persistent, StopOnError, _resume, dumpLog, encoding, _outputPrefix, Destination, Persistent, StopOnError, _resume, dumpLog, encoding, _outputPrefix, Destination,
parsedOptions, _sidecar, (uint)Skipped, ExistingMetadata == false, Trim == false, parsedOptions, _sidecar, (uint)Skipped, ExistingMetadata == false, Trim == false,
Track1Pregap, true, false, DumpSubchannel.Any, 0, false, false, false, false, false, Track1Pregap, true, false, DumpSubchannel.Any, 0, false, false, false, false, false,
true, errorLog, false, 64); true, errorLog, false, 64, true);
new Thread(DoWork).Start(); new Thread(DoWork).Start();
} }