From 6e50f53d7cba30d3ef5170d8479c0e356ee03927 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 11 Dec 2021 19:48:34 +0000 Subject: [PATCH] When dumping an SD/MMC card try to detect if OS buffered reads are failing, and max readable blocks using sequential commands, and downgrade accordingly. Now also detects cards that are totally unreadable. --- Aaru.Core/Devices/Dumping/Dump.cs | 2 +- Aaru.Core/Devices/Dumping/SecureDigital.cs | 74 ++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Aaru.Core/Devices/Dumping/Dump.cs b/Aaru.Core/Devices/Dumping/Dump.cs index d2f1658cc..be7454c8d 100644 --- a/Aaru.Core/Devices/Dumping/Dump.cs +++ b/Aaru.Core/Devices/Dumping/Dump.cs @@ -93,7 +93,7 @@ namespace Aaru.Core.Devices.Dumping readonly DumpSubchannel _subchannel; readonly bool _titleKeys; readonly bool _trim; - readonly bool _useBufferedReads; + bool _useBufferedReads; bool _aborted; AaruContext _ctx; // Main database context Database.Models.Device _dbDev; // Device database entry diff --git a/Aaru.Core/Devices/Dumping/SecureDigital.cs b/Aaru.Core/Devices/Dumping/SecureDigital.cs index a6e3559a5..13445bea4 100644 --- a/Aaru.Core/Devices/Dumping/SecureDigital.cs +++ b/Aaru.Core/Devices/Dumping/SecureDigital.cs @@ -313,6 +313,80 @@ namespace Aaru.Core.Devices.Dumping } } + if(_useBufferedReads && blocksToRead > 1 && !supportsCmd23) + { + while(true) + { + error = _dev.BufferedOsRead(out cmdBuf, 0, blockSize * blocksToRead, + out duration); + + if(error) + blocksToRead /= 2; + + if(!error || + blocksToRead == 1) + break; + + // Device is in timeout, reopen to reset + if(_dev.LastError == 110) + sense = _dev.ReOpen(); + } + + if(error) + { + UpdateStatus?.Invoke("Buffered OS reads are not working, trying direct commands."); + _dumpLog.WriteLine("Buffered OS reads are not working, trying direct commands."); + blocksToRead = 1; + _useBufferedReads = false; + } + } + + if(!_useBufferedReads && blocksToRead > 1 && !supportsCmd23) + { + while(true) + { + error = _dev.ReadMultipleUsingSingle(out cmdBuf, out _, 0, blockSize, blocksToRead, + byteAddressed, timeout, out duration); + + if(error) + blocksToRead /= 2; + + // Device is in timeout, reopen to reset + if(_dev.LastError == 110) + sense = _dev.ReOpen(); + + if(!error || + blocksToRead == 1) + break; + } + + if(error) + { + _dumpLog.WriteLine("ERROR: Cannot get blocks to read, device error {0}.", _dev.LastError); + + StoppingErrorMessage?. + Invoke($"Device error {_dev.LastError} trying to guess ideal transfer length."); + + return; + } + } + + if(blocksToRead == 1) + { + error = _dev.ReadSingleBlock(out cmdBuf, out _, 0, blockSize, byteAddressed, timeout, + out duration); + + if(error) + { + _dumpLog.WriteLine("ERROR: Could not read from device, device error {0}.", _dev.LastError); + + StoppingErrorMessage?. + Invoke($"Device error {_dev.LastError} trying to read from device."); + + return; + } + } + if(supportsCmd23 || blocksToRead == 1) { UpdateStatus?.Invoke($"Device can read {blocksToRead} blocks at a time.");