diff --git a/.idea/.idea.DiscImageChef/.idea/contentModel.xml b/.idea/.idea.DiscImageChef/.idea/contentModel.xml
index c9a11cced..c0c994f7b 100644
--- a/.idea/.idea.DiscImageChef/.idea/contentModel.xml
+++ b/.idea/.idea.DiscImageChef/.idea/contentModel.xml
@@ -1636,6 +1636,8 @@
+
+
diff --git a/DiscImageChef.Gui/Forms/frmMediaScan.xeto b/DiscImageChef.Gui/Forms/frmMediaScan.xeto
new file mode 100644
index 000000000..e88b88442
--- /dev/null
+++ b/DiscImageChef.Gui/Forms/frmMediaScan.xeto
@@ -0,0 +1,60 @@
+
+
\ No newline at end of file
diff --git a/DiscImageChef.Gui/Forms/frmMediaScan.xeto.cs b/DiscImageChef.Gui/Forms/frmMediaScan.xeto.cs
new file mode 100644
index 000000000..27c80b646
--- /dev/null
+++ b/DiscImageChef.Gui/Forms/frmMediaScan.xeto.cs
@@ -0,0 +1,171 @@
+// /***************************************************************************
+// The Disc Image Chef
+// ----------------------------------------------------------------------------
+//
+// Filename : frmMediaScan.xeto.cs
+// Author(s) : Natalia Portillo
+//
+// Component : Media surface scan window.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+// Implements media scan GUI window.
+//
+// --[ License ] --------------------------------------------------------------
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General public License for more details.
+//
+// You should have received a copy of the GNU General public License
+// along with this program. If not, see .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2018 Natalia Portillo
+// ****************************************************************************/
+
+using System;
+using DiscImageChef.CommonTypes;
+using DiscImageChef.Core;
+using DiscImageChef.Core.Devices.Scanning;
+using DiscImageChef.Core.Media.Info;
+using DiscImageChef.Devices;
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
+
+namespace DiscImageChef.Gui.Forms
+{
+ public class frmMediaScan : Form
+ {
+ string devicePath;
+
+ public frmMediaScan(string devicePath, DeviceInfo deviceInfo, ScsiInfo scsiInfo = null)
+ {
+ MediaType mediaType;
+ XamlReader.Load(this);
+
+ this.devicePath = devicePath;
+ btnStop.Visible = false;
+ }
+
+ void OnBtnCancelClick(object sender, EventArgs e)
+ {
+ Close();
+ }
+
+ void OnBtnStopClick(object sender, EventArgs e)
+ {
+ // TODO: Stop
+ }
+
+ // TODO: Allow to save MHDD and ImgBurn log files
+ void OnBtnScanClick(object sender, EventArgs e)
+ {
+ btnStop.Visible = true;
+ btnScan.Visible = false;
+ btnCancel.Visible = false;
+
+ if(devicePath.Length == 2 && devicePath[1] == ':' && devicePath[0] != '/' && char.IsLetter(devicePath[0]))
+ devicePath = "\\\\.\\" + char.ToUpper(devicePath[0]) + ':';
+
+ Device dev = new Device(devicePath);
+
+ if(dev.Error)
+ {
+ MessageBox.Show($"Error {dev.LastError} opening device.", MessageBoxType.Error);
+ btnStop.Visible = false;
+ btnScan.Visible = true;
+ btnCancel.Visible = true;
+
+ return;
+ }
+
+ Statistics.AddDevice(dev);
+
+ ScanResults results;
+
+ switch(dev.Type)
+ {
+ case DeviceType.ATA:
+ results = Ata.Scan(null, null, devicePath, dev);
+ break;
+ case DeviceType.MMC:
+ case DeviceType.SecureDigital:
+ results = SecureDigital.Scan(null, null, devicePath, dev);
+ break;
+ case DeviceType.NVMe:
+ results = Nvme.Scan(null, null, devicePath, dev);
+ break;
+ case DeviceType.ATAPI:
+ case DeviceType.SCSI:
+ results = Scsi.Scan(null, null, devicePath, dev);
+ break;
+ default: throw new NotSupportedException("Unknown device type.");
+ }
+
+ lblTotalTime.Text = lblTotalTime.Text =
+ $"Took a total of {results.TotalTime} seconds ({results.ProcessingTime} processing commands).";
+ lblAvgSpeed.Text = $"Average speed: {results.AvgSpeed:F3} MiB/sec.";
+ lblMaxSpeed.Text = $"Fastest speed burst: {results.MaxSpeed:F3} MiB/sec.";
+ lblMinSpeed.Text = $"Slowest speed burst: {results.MinSpeed:F3} MiB/sec.";
+ lblA.Text = $"{results.A} sectors took less than 3 ms.";
+ lblB.Text = $"{results.B} sectors took less than 10 ms but more than 3 ms.";
+ lblC.Text = $"{results.C} sectors took less than 50 ms but more than 10 ms.";
+ lblD.Text = $"{results.D} sectors took less than 150 ms but more than 50 ms.";
+ lblE.Text = $"{results.E} sectors took less than 500 ms but more than 150 ms.";
+ lblF.Text = $"{results.F} sectors took more than 500 ms.";
+ lblUnreadableSectors.Text = $"{results.UnreadableSectors.Count} sectors could not be read.";
+
+ // TODO: Show list of unreadable sectors
+ /*
+ if(results.UnreadableSectors.Count > 0)
+ foreach(ulong bad in results.UnreadableSectors)
+ string.Format("Sector {0} could not be read", bad);
+*/
+
+ // TODO: Show results
+ /*
+ #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
+ if(results.SeekTotal != 0 || results.SeekMin != double.MaxValue || results.SeekMax != double.MinValue)
+ #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
+ string.Format("Testing {0} seeks, longest seek took {1:F3} ms, fastest one took {2:F3} ms. ({3:F3} ms average)",
+ results.SeekTimes, results.SeekMax, results.SeekMin, results.SeekTotal / 1000);
+ */
+
+ Statistics.AddMediaScan((long)results.A, (long)results.B, (long)results.C, (long)results.D, (long)results.E,
+ (long)results.F, (long)results.Blocks, (long)results.Errored,
+ (long)(results.Blocks - results.Errored));
+ Statistics.AddCommand("media-scan");
+
+ dev.Close();
+
+ btnStop.Visible = false;
+ btnScan.Visible = true;
+ btnCancel.Visible = true;
+ }
+
+ #region XAML IDs
+ Label lblTotalTime;
+ Label lblAvgSpeed;
+ Label lblMaxSpeed;
+ Label lblMinSpeed;
+ Label lblA;
+ Label lblB;
+ Label lblC;
+ Label lblD;
+ Label lblE;
+ Label lblF;
+ Label lblUnreadableSectors;
+ Button btnCancel;
+ Button btnStop;
+ Button btnScan;
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/DiscImageChef.Gui/Panels/pnlScsiInfo.xeto b/DiscImageChef.Gui/Panels/pnlScsiInfo.xeto
index bab264ee5..19cba65fb 100644
--- a/DiscImageChef.Gui/Panels/pnlScsiInfo.xeto
+++ b/DiscImageChef.Gui/Panels/pnlScsiInfo.xeto
@@ -106,5 +106,8 @@
+
+
+
\ No newline at end of file
diff --git a/DiscImageChef.Gui/Panels/pnlScsiInfo.xeto.cs b/DiscImageChef.Gui/Panels/pnlScsiInfo.xeto.cs
index 452012f53..c3b6e6c55 100644
--- a/DiscImageChef.Gui/Panels/pnlScsiInfo.xeto.cs
+++ b/DiscImageChef.Gui/Panels/pnlScsiInfo.xeto.cs
@@ -232,6 +232,22 @@ namespace DiscImageChef.Gui.Panels
dumpForm.Show();
}
+ protected void OnBtnScanClick(object sender, EventArgs e)
+ {
+ if(scsiInfo.MediaType == MediaType.GDR || scsiInfo.MediaType == MediaType.GDROM)
+ {
+ MessageBox.Show("GD-ROM scan support is not yet implemented.", MessageBoxType.Error);
+ return;
+ }
+
+ if((scsiInfo.MediaType == MediaType.XGD || scsiInfo.MediaType == MediaType.XGD2 ||
+ scsiInfo.MediaType == MediaType.XGD3))
+ MessageBox.Show("Scanning Xbox discs is not yet supported.", MessageBoxType.Error);
+
+ frmMediaScan scanForm = new frmMediaScan(devicePath, scsiInfo.DeviceInfo, scsiInfo);
+ scanForm.Show();
+ }
+
#region XAML controls
#pragma warning disable 169
#pragma warning disable 649
@@ -280,6 +296,7 @@ namespace DiscImageChef.Gui.Panels
Button btnDump;
ImageView imgMediaLogo;
SvgImageView svgMediaLogo;
+ Button btnScan;
#pragma warning restore 169
#pragma warning restore 649
#endregion