diff --git a/Aaru.Core/Devices/Dumping/XGD.cs b/Aaru.Core/Devices/Dumping/XGD.cs
index 0af215e92..e198cf5db 100644
--- a/Aaru.Core/Devices/Dumping/XGD.cs
+++ b/Aaru.Core/Devices/Dumping/XGD.cs
@@ -51,6 +51,7 @@ using Aaru.Decoders.SCSI;
using Aaru.Decoders.Xbox;
using Aaru.Devices;
using Schemas;
+using Device = Aaru.Devices.Remote.Device;
using PlatformID = Aaru.CommonTypes.Interop.PlatformID;
using TrackType = Aaru.CommonTypes.Enums.TrackType;
using Version = Aaru.CommonTypes.Interop.Version;
@@ -82,7 +83,7 @@ partial class Dump
if(DetectOS.GetRealPlatformID() != PlatformID.Win32NT)
{
- bool isAdmin = _dev.IsRemote ? _dev.IsRemoteAdmin : DetectOS.IsAdmin;
+ bool isAdmin = _dev is Device remoteDev ? remoteDev.IsAdmin : DetectOS.IsAdmin;
if(!isAdmin)
{
diff --git a/Aaru.Core/Logging/DumpLog.cs b/Aaru.Core/Logging/DumpLog.cs
index 270ebcf00..6184b888e 100644
--- a/Aaru.Core/Logging/DumpLog.cs
+++ b/Aaru.Core/Logging/DumpLog.cs
@@ -114,17 +114,18 @@ public sealed class DumpLog
_logSw.WriteLine();
- if(dev.IsRemote)
+ if(dev is Aaru.Devices.Remote.Device remoteDev)
{
_logSw.WriteLine("################# Remote information #################");
- _logSw.WriteLine("Server: {0}", dev.RemoteApplication);
- _logSw.WriteLine("Version: {0}", dev.RemoteVersion);
+ _logSw.WriteLine("Server: {0}", remoteDev.RemoteApplication);
+ _logSw.WriteLine("Version: {0}", remoteDev.RemoteVersion);
- _logSw.WriteLine("Operating system: {0} {1}", dev.RemoteOperatingSystem, dev.RemoteOperatingSystemVersion);
+ _logSw.WriteLine("Operating system: {0} {1}", remoteDev.RemoteOperatingSystem,
+ remoteDev.RemoteOperatingSystemVersion);
- _logSw.WriteLine("Architecture: {0}", dev.RemoteArchitecture);
- _logSw.WriteLine("Protocol version: {0}", dev.RemoteProtocolVersion);
- _logSw.WriteLine("Running as superuser: {0}", dev.IsRemoteAdmin ? "Yes" : "No");
+ _logSw.WriteLine("Architecture: {0}", remoteDev.RemoteArchitecture);
+ _logSw.WriteLine("Protocol version: {0}", remoteDev.RemoteProtocolVersion);
+ _logSw.WriteLine("Running as superuser: {0}", remoteDev.IsAdmin ? "Yes" : "No");
_logSw.WriteLine("######################################################");
}
diff --git a/Aaru.Devices/Aaru.Devices.csproj b/Aaru.Devices/Aaru.Devices.csproj
index 7811699e2..049e5053c 100644
--- a/Aaru.Devices/Aaru.Devices.csproj
+++ b/Aaru.Devices/Aaru.Devices.csproj
@@ -65,6 +65,7 @@
+
@@ -77,7 +78,6 @@
-
diff --git a/Aaru.Devices/Command.cs b/Aaru.Devices/Command.cs
deleted file mode 100644
index 821c45b51..000000000
--- a/Aaru.Devices/Command.cs
+++ /dev/null
@@ -1,434 +0,0 @@
-// /***************************************************************************
-// Aaru Data Preservation Suite
-// ----------------------------------------------------------------------------
-//
-// Filename : Command.cs
-// Author(s) : Natalia Portillo
-//
-// Component : Direct device access.
-//
-// --[ Description ] ----------------------------------------------------------
-//
-// High level commands used to directly access devices.
-//
-// --[ License ] --------------------------------------------------------------
-//
-// This library is free software; you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General internal License as
-// published by the Free Software Foundation; either version 2.1 of the
-// License, or (at your option) any later version.
-//
-// This library 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
-// Lesser General internal License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, see .
-//
-// ----------------------------------------------------------------------------
-// Copyright © 2011-2022 Natalia Portillo
-// ****************************************************************************/
-
-// ReSharper disable UnusedMember.Global
-
-namespace Aaru.Devices;
-
-using System;
-using Aaru.CommonTypes.Interop;
-using Aaru.Decoders.ATA;
-using Aaru.Devices.Windows;
-using Microsoft.Win32.SafeHandles;
-using PlatformID = Aaru.CommonTypes.Interop.PlatformID;
-
-static class Command
-{
- /// Sends a SCSI command
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// SCSI CDB
- /// Buffer for SCSI command response
- /// Buffer with the SCSI sense
- /// Timeout in seconds
- /// SCSI command transfer direction
- /// Time it took to execute the command in milliseconds
- ///
- /// True if SCSI error returned non-OK status and contains SCSI
- /// sense
- ///
- /// If the specified platform is not supported
- 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();
-
- return SendScsiCommand(ptId, fd, cdb, ref buffer, out senseBuffer, timeout, direction, out duration, out sense);
- }
-
- /// Sends a SCSI command
- /// 0 if no error occurred, otherwise, errno
- /// Platform ID for executing the command
- /// File handle
- /// SCSI CDB
- /// Buffer for SCSI command response
- /// Buffer with the SCSI sense
- /// Timeout in seconds
- /// SCSI command transfer direction
- /// Time it took to execute the command in milliseconds
- ///
- /// True if SCSI error returned non-OK status and contains SCSI
- /// sense
- ///
- /// If the specified platform is not supported
- 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)
- {
- case PlatformID.Win32NT:
- {
- ScsiIoctlDirection dir;
-
- switch(direction)
- {
- case ScsiDirection.In:
- dir = ScsiIoctlDirection.In;
-
- break;
- case ScsiDirection.Out:
- dir = ScsiIoctlDirection.Out;
-
- break;
- default:
- dir = ScsiIoctlDirection.Unspecified;
-
- break;
- }
-
- return Windows.Command.SendScsiCommand((SafeFileHandle)fd, cdb, ref buffer, out senseBuffer, timeout,
- dir, out duration, out sense);
- }
- case PlatformID.Linux:
- {
- Linux.ScsiIoctlDirection dir;
-
- switch(direction)
- {
- case ScsiDirection.In:
- dir = Linux.ScsiIoctlDirection.In;
-
- break;
- case ScsiDirection.Out:
- dir = Linux.ScsiIoctlDirection.Out;
-
- break;
- case ScsiDirection.Bidirectional:
- dir = Linux.ScsiIoctlDirection.Unspecified;
-
- break;
- case ScsiDirection.None:
- dir = Linux.ScsiIoctlDirection.None;
-
- break;
- default:
- dir = Linux.ScsiIoctlDirection.Unknown;
-
- break;
- }
-
- return Linux.Command.SendScsiCommand((int)fd, cdb, ref buffer, out senseBuffer, timeout, dir,
- out duration, out sense);
- }
- default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
- }
- }
-
- /// Sends an ATA command in CHS format
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA returned non-OK status
- /// Registers to send to the device
- /// Registers returned by the device
- /// ATA protocol to use
- /// What register contains the transfer length
- /// Set to true if the transfer length is in block, otherwise it is in bytes
- /// If the specified platform is not supported
- 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, timeout,
- transferBlocks, out duration, out sense);
- }
-
- /// Sends an ATA command in CHS format
- /// 0 if no error occurred, otherwise, errno
- /// Platform ID for executing the command
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA returned non-OK status
- /// Registers to send to the device
- /// Registers returned by the device
- /// ATA protocol to use
- /// What register contains the transfer length
- /// Set to true if the transfer length is in block, otherwise it is in bytes
- /// If the specified platform is not supported
- 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)
- {
- case PlatformID.Win32NT:
- {
- if(Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1 &&
- Environment.OSVersion.ServicePack is "Service Pack 1" or "" ||
- Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0)
- throw new InvalidOperationException("Windows XP or earlier is not supported.");
-
- // Windows NT 4 or earlier, requires special ATA pass thru SCSI. But Aaru cannot run there (or can it?)
- if(Environment.OSVersion.Version.Major <= 4)
- throw new InvalidOperationException("Windows NT 4.0 or earlier is not supported.");
-
- return Windows.Command.SendAtaCommand((SafeFileHandle)fd, registers, out errorRegisters, protocol,
- ref buffer, timeout, out duration, out sense);
- }
- case PlatformID.Linux:
- {
- return Linux.Command.SendAtaCommand((int)fd, registers, out errorRegisters, protocol, transferRegister,
- ref buffer, timeout, transferBlocks, out duration, out sense);
- }
- default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
- }
- }
-
- /// Sends an ATA command in CHS format
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA returned non-OK status
- /// Registers to send to the device
- /// Registers returned by the device
- /// ATA protocol to use
- /// What register contains the transfer length
- /// Set to true if the transfer length is in block, otherwise it is in bytes
- /// If the specified platform is not supported
- 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, timeout,
- transferBlocks, out duration, out sense);
- }
-
- /// Sends an ATA command in 28-bit LBA format
- /// 0 if no error occurred, otherwise, errno
- /// Platform ID for executing the command
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA returned non-OK status
- /// Registers to send to the device
- /// Registers returned by the device
- /// ATA protocol to use
- /// What register contains the transfer length
- /// Set to true if the transfer length is in block, otherwise it is in bytes
- /// If the specified platform is not supported
- 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)
- {
- case PlatformID.Win32NT:
- {
- if(Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1 &&
- Environment.OSVersion.ServicePack is "Service Pack 1" or "" ||
- Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0)
- throw new InvalidOperationException("Windows XP or earlier is not supported.");
-
- // Windows NT 4 or earlier, requires special ATA pass thru SCSI. But Aaru cannot run there (or can it?)
- if(Environment.OSVersion.Version.Major <= 4)
- throw new InvalidOperationException("Windows NT 4.0 or earlier is not supported.");
-
- return Windows.Command.SendAtaCommand((SafeFileHandle)fd, registers, out errorRegisters, protocol,
- ref buffer, timeout, out duration, out sense);
- }
- case PlatformID.Linux:
- {
- return Linux.Command.SendAtaCommand((int)fd, registers, out errorRegisters, protocol, transferRegister,
- ref buffer, timeout, transferBlocks, out duration, out sense);
- }
- default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
- }
- }
-
- /// Sends an ATA command in 48-bit LBA format
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA returned non-OK status
- /// Registers to send to the device
- /// Registers returned by the device
- /// ATA protocol to use
- /// What register contains the transfer length
- /// Set to true if the transfer length is in block, otherwise it is in bytes
- /// If the specified platform is not supported
- 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, timeout,
- transferBlocks, out duration, out sense);
- }
-
- /// Sends an ATA command in 48-bit format
- /// 0 if no error occurred, otherwise, errno
- /// Platform ID for executing the command
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA returned non-OK status
- /// Registers to send to the device
- /// Registers returned by the device
- /// ATA protocol to use
- /// What register contains the transfer length
- /// Set to true if the transfer length is in block, otherwise it is in bytes
- /// If the specified platform is not supported
- 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)
- {
- case PlatformID.Win32NT:
- // No check for Windows version. A 48-bit ATA disk simply does not work on earlier systems
- return Windows.Command.SendAtaCommand((SafeFileHandle)fd, registers, out errorRegisters, protocol,
- ref buffer, timeout, out duration, out sense);
- case PlatformID.Linux:
- return Linux.Command.SendAtaCommand((int)fd, registers, out errorRegisters, protocol, transferRegister,
- ref buffer, timeout, transferBlocks, out duration, out sense);
- default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
- }
- }
-
- /// Sends a MMC/SD command
- /// The result of the command.
- /// File handle
- /// MMC/SD opcode
- /// Buffer for MMC/SD command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if MMC/SD returned non-OK status
- /// True if data is sent from host to card
- /// True if command should be preceded with CMD55
- /// Flags indicating kind and place of response
- /// How many blocks to transfer
- /// Command argument
- /// Response registers
- /// Size of block in bytes
- /// If the specified platform is not supported
- 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,
- ref buffer, out response, out duration, out sense, timeout);
- }
-
- /// Sends a MMC/SD command
- /// The result of the command.
- /// Platform ID for executing the command
- /// File handle
- /// MMC/SD opcode
- /// Buffer for MMC/SD command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if MMC/SD returned non-OK status
- /// True if data is sent from host to card
- /// True if command should be preceded with CMD55
- /// Flags indicating kind and place of response
- /// How many blocks to transfer
- /// Command argument
- /// Response registers
- /// Size of block in bytes
- /// If the specified platform is not supported
- 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)
- {
- case PlatformID.Win32NT:
- return Windows.Command.SendMmcCommand((SafeFileHandle)fd, command, write, isApplication, flags,
- argument, blockSize, blocks, ref buffer, out response,
- out duration, out sense, timeout);
- case PlatformID.Linux:
- return Linux.Command.SendMmcCommand((int)fd, command, write, isApplication, flags, argument, blockSize,
- blocks, ref buffer, out response, out duration, out sense, timeout);
- default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
- }
- }
-
- internal static int SendMultipleMmcCommands(PlatformID ptId, object fd, Device.MmcSingleCommand[] commands,
- out double duration, out bool sense, uint timeout = 0)
- {
- switch(ptId)
- {
- case PlatformID.Win32NT:
- return Windows.Command.SendMultipleMmcCommands((SafeFileHandle)fd, commands, out duration, out sense,
- timeout);
- case PlatformID.Linux:
- return Linux.Command.SendMultipleMmcCommands((int)fd, commands, out duration, out sense, timeout);
- default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
- }
- }
-
- internal static int ReOpen(PlatformID ptId, string devicePath, object fd, out object newFd)
- {
- switch(ptId)
- {
- case PlatformID.Win32NT: return Windows.Command.ReOpen(devicePath, (SafeFileHandle)fd, out newFd);
- case PlatformID.Linux: return Linux.Command.ReOpen(devicePath, (int)fd, out newFd);
- 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.");
- }
- }
-}
\ No newline at end of file
diff --git a/Aaru.Devices/Device/Commands.cs b/Aaru.Devices/Device/Commands.cs
index 8a79de53c..ffc2b8f22 100644
--- a/Aaru.Devices/Device/Commands.cs
+++ b/Aaru.Devices/Device/Commands.cs
@@ -32,7 +32,6 @@
namespace Aaru.Devices;
-using System;
using System.Diagnostics.CodeAnalysis;
using Aaru.Decoders.ATA;
@@ -51,19 +50,14 @@ public partial class Device
/// True if SCSI command returned non-OK status and contains
/// SCSI sense
///
- public int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
- ScsiDirection direction, out double duration, out bool sense)
+ public virtual int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
+ ScsiDirection direction, out double duration, out bool sense)
{
- // We need a timeout
- if(timeout == 0)
- timeout = Timeout > 0 ? Timeout : 15;
+ duration = 0;
+ sense = true;
+ senseBuffer = null;
- if(!(_remote is null))
- return _remote.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, direction, out duration,
- out sense);
-
- return Command.SendScsiCommand(PlatformId, FileHandle, cdb, ref buffer, out senseBuffer, timeout, direction,
- out duration, out sense);
+ return -1;
}
/// Sends an ATA/ATAPI command to this device using CHS addressing
@@ -80,20 +74,15 @@ public partial class Device
///
/// Time it took to execute the command in milliseconds
/// True if ATA/ATAPI command returned non-OK status
- 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)
+ public virtual int SendAtaCommand(AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
{
- // We need a timeout
- if(timeout == 0)
- timeout = Timeout > 0 ? Timeout : 15;
+ duration = 0;
+ sense = true;
+ errorRegisters = default(AtaErrorRegistersChs);
- if(!(_remote is null))
- return _remote.SendAtaCommand(registers, out errorRegisters, protocol, transferRegister, ref buffer,
- timeout, transferBlocks, out duration, out sense);
-
- return Command.SendAtaCommand(PlatformId, FileHandle, registers, out errorRegisters, protocol, transferRegister,
- ref buffer, timeout, transferBlocks, out duration, out sense);
+ return -1;
}
/// Sends an ATA/ATAPI command to this device using 28-bit LBA addressing
@@ -110,20 +99,15 @@ public partial class Device
///
/// Time it took to execute the command in milliseconds
/// True if ATA/ATAPI command returned non-OK status
- 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)
+ public virtual int SendAtaCommand(AtaRegistersLba28 registers, out AtaErrorRegistersLba28 errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
{
- // We need a timeout
- if(timeout == 0)
- timeout = Timeout > 0 ? Timeout : 15;
+ errorRegisters = default(AtaErrorRegistersLba28);
+ duration = 0;
+ sense = true;
- if(!(_remote is null))
- return _remote.SendAtaCommand(registers, out errorRegisters, protocol, transferRegister, ref buffer,
- timeout, transferBlocks, out duration, out sense);
-
- return Command.SendAtaCommand(PlatformId, FileHandle, registers, out errorRegisters, protocol, transferRegister,
- ref buffer, timeout, transferBlocks, out duration, out sense);
+ return -1;
}
/// Sends an ATA/ATAPI command to this device using 48-bit LBA addressing
@@ -140,20 +124,15 @@ public partial class Device
///
/// Time it took to execute the command in milliseconds
/// True if ATA/ATAPI command returned non-OK status
- 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)
+ public virtual int SendAtaCommand(AtaRegistersLba48 registers, out AtaErrorRegistersLba48 errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
{
- // We need a timeout
- if(timeout == 0)
- timeout = Timeout > 0 ? Timeout : 15;
+ errorRegisters = default(AtaErrorRegistersLba48);
+ duration = 0;
+ sense = true;
- if(!(_remote is null))
- return _remote.SendAtaCommand(registers, out errorRegisters, protocol, transferRegister, ref buffer,
- timeout, transferBlocks, out duration, out sense);
-
- return Command.SendAtaCommand(PlatformId, FileHandle, registers, out errorRegisters, protocol, transferRegister,
- ref buffer, timeout, transferBlocks, out duration, out sense);
+ return -1;
}
/// Sends a MMC/SD command to this device
@@ -170,74 +149,15 @@ public partial class Device
/// Command argument
/// Response registers
/// Size of block in bytes
- 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 = 15)
+ public virtual 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 = 15)
{
- // We need a timeout
- if(timeout == 0)
- timeout = Timeout > 0 ? Timeout : 15;
+ response = null;
+ duration = 0;
+ sense = true;
- switch(command)
- {
- case MmcCommands.SendCid when _cachedCid != null:
- {
- DateTime start = DateTime.Now;
- buffer = new byte[_cachedCid.Length];
- Array.Copy(_cachedCid, buffer, buffer.Length);
- response = new uint[4];
- sense = false;
- DateTime end = DateTime.Now;
- duration = (end - start).TotalMilliseconds;
-
- return 0;
- }
- case MmcCommands.SendCsd when _cachedCid != null:
- {
- DateTime start = DateTime.Now;
- buffer = new byte[_cachedCsd.Length];
- Array.Copy(_cachedCsd, buffer, buffer.Length);
- response = new uint[4];
- sense = false;
- DateTime end = DateTime.Now;
- duration = (end - start).TotalMilliseconds;
-
- return 0;
- }
- case (MmcCommands)SecureDigitalCommands.SendScr when _cachedScr != null:
- {
- DateTime start = DateTime.Now;
- buffer = new byte[_cachedScr.Length];
- Array.Copy(_cachedScr, buffer, buffer.Length);
- response = new uint[4];
- sense = false;
- DateTime end = DateTime.Now;
- duration = (end - start).TotalMilliseconds;
-
- return 0;
- }
- case (MmcCommands)SecureDigitalCommands.SendOperatingCondition when _cachedOcr != null:
- case MmcCommands.SendOpCond when _cachedOcr != null:
- {
- DateTime start = DateTime.Now;
- buffer = new byte[_cachedOcr.Length];
- Array.Copy(_cachedOcr, buffer, buffer.Length);
- response = new uint[4];
- sense = false;
- DateTime end = DateTime.Now;
- duration = (end - start).TotalMilliseconds;
-
- return 0;
- }
- }
-
- return _remote is null
- ? Command.SendMmcCommand(PlatformId, FileHandle, command, write, isApplication, flags, argument,
- blockSize, blocks, ref buffer, out response, out duration, out sense,
- timeout) : _remote.SendMmcCommand(command, write, isApplication, flags,
- argument, blockSize, blocks, ref buffer,
- out response, out duration, out sense,
- timeout);
+ return -1;
}
/// Encapsulates a single MMC command to send in a queue
@@ -273,59 +193,18 @@ public partial class Device
/// Set to true if any of the commands returned an error status, false otherwise
/// Maximum allowed time to execute a single command
/// 0 if no error occurred, otherwise, errno
- public int SendMultipleMmcCommands(MmcSingleCommand[] commands, out double duration, out bool sense,
- uint timeout = 15)
+ public virtual int SendMultipleMmcCommands(MmcSingleCommand[] commands, out double duration, out bool sense,
+ uint timeout = 15)
{
- // We need a timeout
- if(timeout == 0)
- timeout = Timeout > 0 ? Timeout : 15;
-
- if(_remote is null)
- return Command.SendMultipleMmcCommands(PlatformId, FileHandle, commands, out duration, out sense, timeout);
-
- if(_remote.ServerProtocolVersion >= 2)
- return _remote.SendMultipleMmcCommands(commands, out duration, out sense, timeout);
-
- var error = 0;
duration = 0;
- sense = false;
+ sense = true;
- foreach(MmcSingleCommand command in commands)
- {
- int singleError = _remote.SendMmcCommand(command.command, command.write, command.isApplication,
- command.flags, command.argument, command.blockSize, command.blocks,
- ref command.buffer, out command.response, out double cmdDuration,
- out bool cmdSense, timeout);
-
- if(error == 0 &&
- singleError != 0)
- error = singleError;
-
- duration += cmdDuration;
-
- if(cmdSense)
- sense = true;
- }
-
- return error;
+ return -1;
}
/// Closes then immediately reopens a device
/// Returned error number if any
- public bool ReOpen()
- {
- if(!(_remote is null))
- return _remote.ReOpen();
-
- int ret = Command.ReOpen(PlatformId, _devicePath, FileHandle, out object newFileHandle);
-
- FileHandle = newFileHandle;
-
- Error = ret != 0;
- LastError = ret;
-
- return Error;
- }
+ public virtual bool ReOpen() => false;
/// Reads data using operating system buffers.
/// Data buffer
@@ -333,16 +212,11 @@ public partial class Device
/// Number of bytes to read
/// Total time in milliseconds the reading took
/// true if there was an error, false otherwise
- public bool BufferedOsRead(out byte[] buffer, long offset, uint length, out double duration)
+ public virtual 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);
+ buffer = null;
+ duration = 0;
- int ret = Command.BufferedOsRead(PlatformId, FileHandle, out buffer, offset, length, out duration);
-
- Error = ret != 0;
- LastError = ret;
-
- return Error;
+ return false;
}
}
\ No newline at end of file
diff --git a/Aaru.Devices/Device/Variables.cs b/Aaru.Devices/Device/Variables.cs
index 7e1d5dac6..5280936e3 100644
--- a/Aaru.Devices/Device/Variables.cs
+++ b/Aaru.Devices/Device/Variables.cs
@@ -55,10 +55,6 @@ public partial class Device
/// The Platform ID
public PlatformID PlatformId { get; private protected set; }
- /// Gets the file handle representing this device
- /// The file handle
- public object FileHandle { get; private protected set; }
-
/// Gets or sets the standard timeout for commands sent to this device
/// The timeout in seconds
public uint Timeout { get; set; }
@@ -162,33 +158,5 @@ public partial class Device
/// Contains the PCMCIA CIS if applicable
public byte[] Cis { get; private protected set; }
- private protected Remote.Remote _remote;
- bool? _isRemoteAdmin;
private protected string _devicePath;
-
- /// Returns if remote is running under administrative (aka root) privileges
- public bool IsRemoteAdmin
- {
- get
- {
- _isRemoteAdmin ??= _remote.IsRoot;
-
- return _isRemoteAdmin == true;
- }
- }
-
- /// Current device is remote
- public bool IsRemote => _remote != null;
- /// Remote application
- public string RemoteApplication => _remote?.ServerApplication;
- /// Remote application server
- public string RemoteVersion => _remote?.ServerVersion;
- /// Remote operating system name
- public string RemoteOperatingSystem => _remote?.ServerOperatingSystem;
- /// Remote operating system version
- public string RemoteOperatingSystemVersion => _remote?.ServerOperatingSystemVersion;
- /// Remote architecture
- public string RemoteArchitecture => _remote?.ServerArchitecture;
- /// Remote protocol version
- public int RemoteProtocolVersion => _remote?.ServerProtocolVersion ?? 0;
}
\ No newline at end of file
diff --git a/Aaru.Devices/Linux/Command.cs b/Aaru.Devices/Linux/Command.cs
index c7259440b..fd4e53237 100644
--- a/Aaru.Devices/Linux/Command.cs
+++ b/Aaru.Devices/Linux/Command.cs
@@ -39,24 +39,16 @@ using System.Text;
using Aaru.CommonTypes.Interop;
using Aaru.Decoders.ATA;
-static class Command
+partial class Device
{
- /// Sends a SCSI command
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// SCSI CDB
- /// Buffer for SCSI command response
- /// Buffer with the SCSI sense
- /// Timeout in seconds
- /// SCSI command transfer direction
- /// Time it took to execute the command in milliseconds
- ///
- /// True if SCSI error returned non-OK status and contains SCSI
- /// sense
- ///
- internal static int SendScsiCommand(int fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
- ScsiIoctlDirection direction, out double duration, out bool sense)
+ ///
+ public override int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
+ ScsiDirection direction, out double duration, out bool sense)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
senseBuffer = null;
duration = 0;
sense = false;
@@ -64,6 +56,32 @@ static class Command
if(buffer == null)
return -1;
+ ScsiIoctlDirection dir;
+
+ switch(direction)
+ {
+ case ScsiDirection.In:
+ dir = ScsiIoctlDirection.In;
+
+ break;
+ case ScsiDirection.Out:
+ dir = ScsiIoctlDirection.Out;
+
+ break;
+ case ScsiDirection.Bidirectional:
+ dir = ScsiIoctlDirection.Unspecified;
+
+ break;
+ case ScsiDirection.None:
+ dir = ScsiIoctlDirection.None;
+
+ break;
+ default:
+ dir = ScsiIoctlDirection.Unknown;
+
+ break;
+ }
+
var ioHdr = new SgIoHdrT();
senseBuffer = new byte[64];
@@ -71,7 +89,7 @@ static class Command
ioHdr.interface_id = 'S';
ioHdr.cmd_len = (byte)cdb.Length;
ioHdr.mx_sb_len = (byte)senseBuffer.Length;
- ioHdr.dxfer_direction = direction;
+ ioHdr.dxfer_direction = dir;
ioHdr.dxfer_len = (uint)buffer.Length;
ioHdr.dxferp = Marshal.AllocHGlobal(buffer.Length);
ioHdr.cmdp = Marshal.AllocHGlobal(cdb.Length);
@@ -84,7 +102,7 @@ static class Command
Marshal.Copy(senseBuffer, 0, ioHdr.sbp, senseBuffer.Length);
DateTime start = DateTime.UtcNow;
- int error = Extern.ioctlSg(fd, LinuxIoctl.SgIo, ref ioHdr);
+ int error = Extern.ioctlSg(_fileDescriptor, LinuxIoctl.SgIo, ref ioHdr);
DateTime end = DateTime.UtcNow;
if(error < 0)
@@ -108,7 +126,7 @@ static class Command
/// Converts ATA protocol to SG_IO direction
/// ATA protocol
/// SG_IO direction
- static ScsiIoctlDirection AtaProtocolToScsiDirection(AtaProtocol protocol)
+ static ScsiDirection AtaProtocolToScsiDirection(AtaProtocol protocol)
{
switch(protocol)
{
@@ -117,31 +135,24 @@ static class Command
case AtaProtocol.HardReset:
case AtaProtocol.NonData:
case AtaProtocol.SoftReset:
- case AtaProtocol.ReturnResponse: return ScsiIoctlDirection.None;
+ case AtaProtocol.ReturnResponse: return ScsiDirection.None;
case AtaProtocol.PioIn:
- case AtaProtocol.UDmaIn: return ScsiIoctlDirection.In;
+ case AtaProtocol.UDmaIn: return ScsiDirection.In;
case AtaProtocol.PioOut:
- case AtaProtocol.UDmaOut: return ScsiIoctlDirection.Out;
- default: return ScsiIoctlDirection.Unspecified;
+ case AtaProtocol.UDmaOut: return ScsiDirection.Out;
+ default: return ScsiDirection.Unspecified;
}
}
- /// Sends an ATA command in CHS mode
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA error returned non-OK status
- /// Registers to send to drive
- /// Registers returned by drive
- /// ATA protocol to use
- /// Which register contains the transfer count
- /// Set to true if the transfer count is in blocks, otherwise it is in bytes
- internal static int SendAtaCommand(int fd, AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters,
+ ///
+ public override int SendAtaCommand(AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters,
AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
uint timeout, bool transferBlocks, out double duration, out bool sense)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
duration = 0;
sense = false;
errorRegisters = new AtaErrorRegistersChs();
@@ -185,7 +196,7 @@ static class Command
cdb[13] = registers.DeviceHead;
cdb[14] = registers.Command;
- int error = SendScsiCommand(fd, cdb, ref buffer, out byte[] senseBuffer, timeout,
+ int error = SendScsiCommand(cdb, ref buffer, out byte[] senseBuffer, timeout,
AtaProtocolToScsiDirection(protocol), out duration, out sense);
if(senseBuffer.Length < 22 ||
@@ -206,22 +217,15 @@ static class Command
return error;
}
- /// Sends an ATA command in 28-bit LBA mode
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA error returned non-OK status
- /// Registers to send to drive
- /// Registers returned by drive
- /// ATA protocol to use
- /// Which register contains the transfer count
- /// Set to true if the transfer count is in blocks, otherwise it is in bytes
- internal static int SendAtaCommand(int fd, AtaRegistersLba28 registers, out AtaErrorRegistersLba28 errorRegisters,
+ ///
+ public override int SendAtaCommand(AtaRegistersLba28 registers, out AtaErrorRegistersLba28 errorRegisters,
AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
uint timeout, bool transferBlocks, out double duration, out bool sense)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
duration = 0;
sense = false;
errorRegisters = new AtaErrorRegistersLba28();
@@ -265,7 +269,7 @@ static class Command
cdb[13] = registers.DeviceHead;
cdb[14] = registers.Command;
- int error = SendScsiCommand(fd, cdb, ref buffer, out byte[] senseBuffer, timeout,
+ int error = SendScsiCommand(cdb, ref buffer, out byte[] senseBuffer, timeout,
AtaProtocolToScsiDirection(protocol), out duration, out sense);
if(senseBuffer.Length < 22 ||
@@ -286,22 +290,15 @@ static class Command
return error;
}
- /// Sends an ATA command in 48-bit LBA mode
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA error returned non-OK status
- /// Registers to send to drive
- /// Registers returned by drive
- /// ATA protocol to use
- /// Which register contains the transfer count
- /// Set to true if the transfer count is in blocks, otherwise it is in bytes
- internal static int SendAtaCommand(int fd, AtaRegistersLba48 registers, out AtaErrorRegistersLba48 errorRegisters,
+ ///
+ public override int SendAtaCommand(AtaRegistersLba48 registers, out AtaErrorRegistersLba48 errorRegisters,
AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
uint timeout, bool transferBlocks, out double duration, out bool sense)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
duration = 0;
sense = false;
errorRegisters = new AtaErrorRegistersLba48();
@@ -351,7 +348,7 @@ static class Command
cdb[13] = registers.DeviceHead;
cdb[14] = registers.Command;
- int error = SendScsiCommand(fd, cdb, ref buffer, out byte[] senseBuffer, timeout,
+ int error = SendScsiCommand(cdb, ref buffer, out byte[] senseBuffer, timeout,
AtaProtocolToScsiDirection(protocol), out duration, out sense);
if(senseBuffer.Length < 22 ||
@@ -377,25 +374,71 @@ static class Command
return error;
}
- /// Sends a MMC/SD command
- /// The result of the command.
- /// File handle
- /// MMC/SD opcode
- /// Buffer for MMC/SD command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if MMC/SD returned non-OK status
- /// True if data is sent from host to card
- /// True if command should be preceded with CMD55
- /// Flags indicating kind and place of response
- /// How many blocks to transfer
- /// Command argument
- /// Response registers
- /// Size of block in bytes
- internal static int SendMmcCommand(int fd, MmcCommands command, bool write, bool isApplication, MmcFlags flags,
+ ///
+ public override 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)
+ out uint[] response, out double duration, out bool sense, uint timeout = 15)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
+ DateTime start;
+ DateTime end;
+
+ switch(command)
+ {
+ case MmcCommands.SendCid when _cachedCid != null:
+ {
+ start = DateTime.Now;
+ buffer = new byte[_cachedCid.Length];
+ Array.Copy(_cachedCid, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case MmcCommands.SendCsd when _cachedCid != null:
+ {
+ start = DateTime.Now;
+ buffer = new byte[_cachedCsd.Length];
+ Array.Copy(_cachedCsd, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case (MmcCommands)SecureDigitalCommands.SendScr when _cachedScr != null:
+ {
+ start = DateTime.Now;
+ buffer = new byte[_cachedScr.Length];
+ Array.Copy(_cachedScr, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case (MmcCommands)SecureDigitalCommands.SendOperatingCondition when _cachedOcr != null:
+ case MmcCommands.SendOpCond when _cachedOcr != null:
+ {
+ start = DateTime.Now;
+ buffer = new byte[_cachedOcr.Length];
+ Array.Copy(_cachedOcr, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ }
+
response = null;
duration = 0;
sense = false;
@@ -425,9 +468,9 @@ static class Command
Marshal.Copy(buffer, 0, bufPtr, buffer.Length);
- DateTime start = DateTime.UtcNow;
- int error = Extern.ioctlMmc(fd, LinuxIoctl.MmcIocCmd, ref ioCmd);
- DateTime end = DateTime.UtcNow;
+ start = DateTime.UtcNow;
+ int error = Extern.ioctlMmc(_fileDescriptor, LinuxIoctl.MmcIocCmd, ref ioCmd);
+ end = DateTime.UtcNow;
sense |= error < 0;
@@ -444,9 +487,14 @@ static class Command
return error;
}
- internal static int SendMultipleMmcCommands(int fd, Device.MmcSingleCommand[] commands, out double duration,
- out bool sense, uint timeout = 0)
+ ///
+ public override int SendMultipleMmcCommands(MmcSingleCommand[] commands, out double duration, out bool sense,
+ uint timeout = 15)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
duration = 0;
sense = false;
int off;
@@ -506,7 +554,7 @@ static class Command
// Send command
DateTime start = DateTime.UtcNow;
- int error = Extern.ioctlMmcMulti(fd, LinuxIoctl.MmcIocMultiCmd, ioMultiCmdPtr);
+ int error = Extern.ioctlMmcMulti(_fileDescriptor, LinuxIoctl.MmcIocMultiCmd, ioMultiCmdPtr);
DateTime end = DateTime.UtcNow;
sense |= error < 0;
@@ -549,35 +597,61 @@ static class Command
return error;
}
- internal static int ReOpen(string devicePath, int fd, out object newFd)
- {
- newFd = -1;
+ ///
+ public override bool ReOpen()
- int ret = Extern.close(fd);
+ {
+ int ret = Extern.close(_fileDescriptor);
if(ret < 0)
- return Marshal.GetLastWin32Error();
+ {
+ LastError = Marshal.GetLastWin32Error();
+ Error = true;
- newFd = Extern.open(devicePath, FileFlags.ReadWrite | FileFlags.NonBlocking | FileFlags.CreateNew);
+ return true;
+ }
- if((int)newFd >= 0)
- return 0;
+ int newFd = Extern.open(_devicePath, FileFlags.ReadWrite | FileFlags.NonBlocking | FileFlags.CreateNew);
+
+ if(newFd >= 0)
+ {
+ Error = false;
+ _fileDescriptor = newFd;
+
+ return false;
+ }
int error = Marshal.GetLastWin32Error();
if(error != 13 &&
error != 30)
- return Marshal.GetLastWin32Error();
+ {
+ LastError = Marshal.GetLastWin32Error();
+ Error = true;
- newFd = Extern.open(devicePath, FileFlags.Readonly | FileFlags.NonBlocking);
+ return true;
+ }
- return (int)newFd < 0 ? Marshal.GetLastWin32Error() : 0;
+ newFd = Extern.open(_devicePath, FileFlags.Readonly | FileFlags.NonBlocking);
+
+ if(newFd < 0)
+ {
+ LastError = Marshal.GetLastWin32Error();
+ Error = true;
+
+ return true;
+ }
+
+ Error = false;
+ _fileDescriptor = newFd;
+
+ return false;
}
/// Reads the contents of a symbolic link
/// Path to the symbolic link
/// Contents of the symbolic link
- internal static string ReadLink(string path)
+ static string ReadLink(string path)
{
IntPtr buf = Marshal.AllocHGlobal(4096);
int resultSize;
@@ -608,13 +682,15 @@ static class Command
return Encoding.ASCII.GetString(resultString);
}
- internal static int BufferedOsRead(int fd, out byte[] buffer, long offset, uint length, out double duration)
+ ///
+ public override bool BufferedOsRead(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);
+ long sense = Extern.lseek(_fileDescriptor, offset, SeekWhence.Begin);
DateTime end = DateTime.Now;
@@ -622,10 +698,14 @@ static class Command
{
duration = (end - start).TotalMilliseconds;
- return Marshal.GetLastWin32Error();
+ Error = true;
+ LastError = Marshal.GetLastWin32Error();
+
+ return true;
}
- sense = DetectOS.Is64Bit ? Extern.read64(fd, buffer, length) : Extern.read(fd, buffer, (int)length);
+ sense = DetectOS.Is64Bit ? Extern.read64(_fileDescriptor, buffer, length)
+ : Extern.read(_fileDescriptor, buffer, (int)length);
end = DateTime.Now;
duration = (end - start).TotalMilliseconds;
@@ -637,6 +717,9 @@ static class Command
else if(errno == 0)
errno = -22;
- return errno;
+ LastError = errno;
+ Error = errno == 0;
+
+ return errno != 0;
}
}
\ No newline at end of file
diff --git a/Aaru.Devices/Linux/Device.cs b/Aaru.Devices/Linux/Device.cs
index 4eb3d11ca..4e723ea10 100644
--- a/Aaru.Devices/Linux/Device.cs
+++ b/Aaru.Devices/Linux/Device.cs
@@ -46,31 +46,34 @@ using VendorString = Aaru.Decoders.MMC.VendorString;
///
[SupportedOSPlatform("linux")]
-public class Device : Devices.Device
+partial class Device : Devices.Device
{
+ /// Gets the file handle representing this device
+ /// The file handle
+ int _fileDescriptor;
+
Device() {}
- public new static Device Create(string devicePath)
+ internal new static Device Create(string devicePath)
{
var dev = new Device
{
- PlatformId = DetectOS.GetRealPlatformID(),
- Timeout = 15,
- Error = false,
- IsRemovable = false
+ PlatformId = DetectOS.GetRealPlatformID(),
+ Timeout = 15,
+ Error = false,
+ IsRemovable = false,
+ _fileDescriptor = Extern.open(devicePath, FileFlags.ReadWrite | FileFlags.NonBlocking | FileFlags.CreateNew)
};
- dev.FileHandle = Extern.open(devicePath, FileFlags.ReadWrite | FileFlags.NonBlocking | FileFlags.CreateNew);
-
- if((int)dev.FileHandle < 0)
+ if(dev._fileDescriptor < 0)
{
dev.LastError = Marshal.GetLastWin32Error();
if(dev.LastError is 13 or 30) // EACCES or EROFS
{
- dev.FileHandle = Extern.open(devicePath, FileFlags.Readonly | FileFlags.NonBlocking);
+ dev._fileDescriptor = Extern.open(devicePath, FileFlags.Readonly | FileFlags.NonBlocking);
- if((int)dev.FileHandle < 0)
+ if(dev._fileDescriptor < 0)
{
dev.Error = true;
dev.LastError = Marshal.GetLastWin32Error();
@@ -92,23 +95,22 @@ public class Device : Devices.Device
dev.Type = DeviceType.Unknown;
dev.ScsiType = PeripheralDeviceTypes.UnknownDevice;
- byte[] ataBuf;
- byte[] inqBuf = null;
-
if(dev.Error)
throw new DeviceException(dev.LastError);
+ string devPath;
+
if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/st", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/sg", StringComparison.Ordinal))
- if(!dev.ScsiInquiry(out inqBuf, out _))
+ if(!dev.ScsiInquiry(out byte[] _, out _))
dev.Type = DeviceType.SCSI;
// MultiMediaCard and SecureDigital go here
else if(devicePath.StartsWith("/dev/mmcblk", StringComparison.Ordinal))
{
- string devPath = devicePath.Substring(5);
+ devPath = devicePath[5..];
if(File.Exists("/sys/block/" + devPath + "/device/csd"))
{
@@ -179,21 +181,23 @@ public class Device : Devices.Device
#endregion SecureDigital / MultiMediaCard
#region USB
+ string resolvedLink;
+
if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
{
- string devPath = devicePath.Substring(5);
+ devPath = devicePath[5..];
if(Directory.Exists("/sys/block/" + devPath))
{
- string resolvedLink = Command.ReadLink("/sys/block/" + devPath);
+ resolvedLink = ReadLink("/sys/block/" + devPath);
if(!string.IsNullOrEmpty(resolvedLink))
{
- resolvedLink = "/sys" + resolvedLink.Substring(2);
+ resolvedLink = "/sys" + resolvedLink[2..];
- while(resolvedLink.Contains("usb"))
+ while(resolvedLink?.Contains("usb") == true)
{
resolvedLink = Path.GetDirectoryName(resolvedLink);
@@ -257,128 +261,121 @@ public class Device : Devices.Device
#endregion USB
#region FireWire
- {
- if(true)
- {
- if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
- devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
- devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
- {
- string devPath = devicePath.Substring(5);
-
- if(Directory.Exists("/sys/block/" + devPath))
- {
- string resolvedLink = Command.ReadLink("/sys/block/" + devPath);
- resolvedLink = "/sys" + resolvedLink.Substring(2);
-
- if(!string.IsNullOrEmpty(resolvedLink))
- while(resolvedLink.Contains("firewire"))
- {
- resolvedLink = Path.GetDirectoryName(resolvedLink);
-
- if(!File.Exists(resolvedLink + "/model") ||
- !File.Exists(resolvedLink + "/vendor") ||
- !File.Exists(resolvedLink + "/guid"))
- continue;
-
- var fwSr = new StreamReader(resolvedLink + "/model");
- string fwTemp = fwSr.ReadToEnd();
-
- uint.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture,
- out dev._firewireModel);
-
- fwSr.Close();
-
- fwSr = new StreamReader(resolvedLink + "/vendor");
- fwTemp = fwSr.ReadToEnd();
-
- uint.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture,
- out dev._firewireVendor);
-
- fwSr.Close();
-
- fwSr = new StreamReader(resolvedLink + "/guid");
- fwTemp = fwSr.ReadToEnd();
-
- ulong.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture,
- out dev._firewireGuid);
-
- fwSr.Close();
-
- if(File.Exists(resolvedLink + "/model_name"))
- {
- fwSr = new StreamReader(resolvedLink + "/model_name");
- dev.FireWireModelName = fwSr.ReadToEnd().Trim();
- fwSr.Close();
- }
-
- if(File.Exists(resolvedLink + "/vendor_name"))
- {
- fwSr = new StreamReader(resolvedLink + "/vendor_name");
- dev.FireWireVendorName = fwSr.ReadToEnd().Trim();
- fwSr.Close();
- }
-
- dev.IsFireWire = true;
-
- break;
- }
- }
- }
- }
-
- // TODO: Implement for other operating systems
- else
- dev.IsFireWire = false;
- }
- #endregion FireWire
-
- #region PCMCIA
if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
{
- string devPath = devicePath.Substring(5);
+ devPath = devicePath[5..];
if(Directory.Exists("/sys/block/" + devPath))
{
- string resolvedLink = Command.ReadLink("/sys/block/" + devPath);
- resolvedLink = "/sys" + resolvedLink.Substring(2);
+ resolvedLink = ReadLink("/sys/block/" + devPath);
+ resolvedLink = "/sys" + resolvedLink[2..];
if(!string.IsNullOrEmpty(resolvedLink))
- while(resolvedLink.Contains("/sys/devices"))
+ while(resolvedLink?.Contains("firewire") == true)
{
resolvedLink = Path.GetDirectoryName(resolvedLink);
- if(!Directory.Exists(resolvedLink + "/pcmcia_socket"))
+ if(!File.Exists(resolvedLink + "/model") ||
+ !File.Exists(resolvedLink + "/vendor") ||
+ !File.Exists(resolvedLink + "/guid"))
continue;
- string[] subdirs = Directory.GetDirectories(resolvedLink + "/pcmcia_socket", "pcmcia_socket*",
- SearchOption.TopDirectoryOnly);
+ var fwSr = new StreamReader(resolvedLink + "/model");
+ string fwTemp = fwSr.ReadToEnd();
- if(subdirs.Length <= 0)
- continue;
+ uint.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture,
+ out dev._firewireModel);
- string possibleDir = Path.Combine(resolvedLink, "pcmcia_socket", subdirs[0]);
+ fwSr.Close();
- if(!File.Exists(possibleDir + "/card_type") ||
- !File.Exists(possibleDir + "/cis"))
- continue;
+ fwSr = new StreamReader(resolvedLink + "/vendor");
+ fwTemp = fwSr.ReadToEnd();
- var cisFs = new FileStream(possibleDir + "/cis", FileMode.Open, FileAccess.Read);
+ uint.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture,
+ out dev._firewireVendor);
- var cisBuf = new byte[65536];
- int cisCount = cisFs.Read(cisBuf, 0, 65536);
- dev.Cis = new byte[cisCount];
- Array.Copy(cisBuf, 0, dev.Cis, 0, cisCount);
- cisFs.Close();
+ fwSr.Close();
- dev.IsPcmcia = true;
+ fwSr = new StreamReader(resolvedLink + "/guid");
+ fwTemp = fwSr.ReadToEnd();
+
+ ulong.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture,
+ out dev._firewireGuid);
+
+ fwSr.Close();
+
+ if(File.Exists(resolvedLink + "/model_name"))
+ {
+ fwSr = new StreamReader(resolvedLink + "/model_name");
+ dev.FireWireModelName = fwSr.ReadToEnd().Trim();
+ fwSr.Close();
+ }
+
+ if(File.Exists(resolvedLink + "/vendor_name"))
+ {
+ fwSr = new StreamReader(resolvedLink + "/vendor_name");
+ dev.FireWireVendorName = fwSr.ReadToEnd().Trim();
+ fwSr.Close();
+ }
+
+ dev.IsFireWire = true;
break;
}
}
}
+ #endregion FireWire
+
+ #region PCMCIA
+ if(!devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) &&
+ !devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) &&
+ !devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
+ return dev;
+
+ devPath = devicePath[5..];
+
+ if(!Directory.Exists("/sys/block/" + devPath))
+ return dev;
+
+ resolvedLink = ReadLink("/sys/block/" + devPath);
+ resolvedLink = "/sys" + resolvedLink[2..];
+
+ if(string.IsNullOrEmpty(resolvedLink))
+ return dev;
+
+ while(resolvedLink.Contains("/sys/devices"))
+ {
+ resolvedLink = Path.GetDirectoryName(resolvedLink);
+
+ if(!Directory.Exists(resolvedLink + "/pcmcia_socket"))
+ continue;
+
+ string[] subdirs = Directory.GetDirectories(resolvedLink + "/pcmcia_socket", "pcmcia_socket*",
+ SearchOption.TopDirectoryOnly);
+
+ if(subdirs.Length <= 0)
+ continue;
+
+ string possibleDir = Path.Combine(resolvedLink, "pcmcia_socket", subdirs[0]);
+
+ if(!File.Exists(possibleDir + "/card_type") ||
+ !File.Exists(possibleDir + "/cis"))
+ continue;
+
+ var cisFs = new FileStream(possibleDir + "/cis", FileMode.Open, FileAccess.Read);
+
+ var cisBuf = new byte[65536];
+ int cisCount = cisFs.Read(cisBuf, 0, 65536);
+ dev.Cis = new byte[cisCount];
+ Array.Copy(cisBuf, 0, dev.Cis, 0, cisCount);
+ cisFs.Close();
+
+ dev.IsPcmcia = true;
+
+ break;
+ }
#endregion PCMCIA
return dev;
@@ -399,11 +396,11 @@ public class Device : Devices.Device
///
public override void Close()
{
- if(FileHandle == null)
+ if(_fileDescriptor == 0)
return;
- Extern.close((int)FileHandle);
+ Extern.close(_fileDescriptor);
- FileHandle = null;
+ _fileDescriptor = 0;
}
}
\ No newline at end of file
diff --git a/Aaru.Devices/Remote/Command.cs b/Aaru.Devices/Remote/Command.cs
new file mode 100644
index 000000000..8f0b52035
--- /dev/null
+++ b/Aaru.Devices/Remote/Command.cs
@@ -0,0 +1,199 @@
+// /***************************************************************************
+// Aaru Data Preservation Suite
+// ----------------------------------------------------------------------------
+//
+// Filename : Commands.cs
+// Author(s) : Natalia Portillo
+//
+// Component : Direct device access.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+// Sends commands to devices.
+//
+// --[ License ] --------------------------------------------------------------
+//
+// This library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 2.1 of the
+// License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, see .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2022 Natalia Portillo
+// ****************************************************************************/
+
+namespace Aaru.Devices.Remote;
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using Aaru.Decoders.ATA;
+
+[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
+public partial class Device
+{
+ ///
+ public override int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
+ ScsiDirection direction, out double duration, out bool sense)
+ {
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
+ return _remote.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, direction, out duration, out sense);
+ }
+
+ ///
+ public override int SendAtaCommand(AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
+ {
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
+ return _remote.SendAtaCommand(registers, out errorRegisters, protocol, transferRegister, ref buffer, timeout,
+ transferBlocks, out duration, out sense);
+ }
+
+ ///
+ public override int SendAtaCommand(AtaRegistersLba28 registers, out AtaErrorRegistersLba28 errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
+ {
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
+ return _remote.SendAtaCommand(registers, out errorRegisters, protocol, transferRegister, ref buffer, timeout,
+ transferBlocks, out duration, out sense);
+ }
+
+ ///
+ public override int SendAtaCommand(AtaRegistersLba48 registers, out AtaErrorRegistersLba48 errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
+ {
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
+ return _remote.SendAtaCommand(registers, out errorRegisters, protocol, transferRegister, ref buffer, timeout,
+ transferBlocks, out duration, out sense);
+ }
+
+ ///
+ public override 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 = 15)
+ {
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
+ switch(command)
+ {
+ case MmcCommands.SendCid when _cachedCid != null:
+ {
+ DateTime start = DateTime.Now;
+ buffer = new byte[_cachedCid.Length];
+ Array.Copy(_cachedCid, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ DateTime end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case MmcCommands.SendCsd when _cachedCid != null:
+ {
+ DateTime start = DateTime.Now;
+ buffer = new byte[_cachedCsd.Length];
+ Array.Copy(_cachedCsd, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ DateTime end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case (MmcCommands)SecureDigitalCommands.SendScr when _cachedScr != null:
+ {
+ DateTime start = DateTime.Now;
+ buffer = new byte[_cachedScr.Length];
+ Array.Copy(_cachedScr, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ DateTime end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case (MmcCommands)SecureDigitalCommands.SendOperatingCondition when _cachedOcr != null:
+ case MmcCommands.SendOpCond when _cachedOcr != null:
+ {
+ DateTime start = DateTime.Now;
+ buffer = new byte[_cachedOcr.Length];
+ Array.Copy(_cachedOcr, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ DateTime end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ }
+
+ return _remote.SendMmcCommand(command, write, isApplication, flags, argument, blockSize, blocks, ref buffer,
+ out response, out duration, out sense, timeout);
+ }
+
+ ///
+ public override int SendMultipleMmcCommands(MmcSingleCommand[] commands, out double duration, out bool sense,
+ uint timeout = 15)
+ {
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
+ if(_remote.ServerProtocolVersion >= 2)
+ return _remote.SendMultipleMmcCommands(commands, out duration, out sense, timeout);
+
+ var error = 0;
+ duration = 0;
+ sense = false;
+
+ foreach(MmcSingleCommand command in commands)
+ {
+ int singleError = _remote.SendMmcCommand(command.command, command.write, command.isApplication,
+ command.flags, command.argument, command.blockSize, command.blocks,
+ ref command.buffer, out command.response, out double cmdDuration,
+ out bool cmdSense, timeout);
+
+ if(error == 0 &&
+ singleError != 0)
+ error = singleError;
+
+ duration += cmdDuration;
+
+ if(cmdSense)
+ sense = true;
+ }
+
+ return error;
+ }
+
+ ///
+ public override bool ReOpen() => _remote.ReOpen();
+
+ ///
+ public override bool BufferedOsRead(out byte[] buffer, long offset, uint length, out double duration) =>
+ _remote.BufferedOsRead(out buffer, offset, length, out duration);
+}
\ No newline at end of file
diff --git a/Aaru.Devices/Remote/Device.cs b/Aaru.Devices/Remote/Device.cs
index 74482aeb8..c73117dd6 100644
--- a/Aaru.Devices/Remote/Device.cs
+++ b/Aaru.Devices/Remote/Device.cs
@@ -39,14 +39,43 @@ using Aaru.CommonTypes.Structs.Devices.SCSI;
using Aaru.Decoders.SecureDigital;
///
-public sealed class Device : Devices.Device
+public sealed partial class Device : Devices.Device
{
+ Remote _remote;
+
+ /// Returns if remote is running under administrative (aka root) privileges
+ public bool IsAdmin
+ {
+ get
+ {
+ _isRemoteAdmin ??= _remote.IsRoot;
+
+ return _isRemoteAdmin == true;
+ }
+ }
+
+ /// Current device is remote
+ public bool IsRemote => _remote != null;
+ /// Remote application
+ public string RemoteApplication => _remote?.ServerApplication;
+ /// Remote application server
+ public string RemoteVersion => _remote?.ServerVersion;
+ /// Remote operating system name
+ public string RemoteOperatingSystem => _remote?.ServerOperatingSystem;
+ /// Remote operating system version
+ public string RemoteOperatingSystemVersion => _remote?.ServerOperatingSystemVersion;
+ /// Remote architecture
+ public string RemoteArchitecture => _remote?.ServerArchitecture;
+ /// Remote protocol version
+ public int RemoteProtocolVersion => _remote?.ServerProtocolVersion ?? 0;
+ bool? _isRemoteAdmin;
+
Device() {}
/// Opens the device for sending direct commands
/// AaruRemote URI
/// Device
- public static Device Create(Uri aaruUri)
+ internal static Device Create(Uri aaruUri)
{
var dev = new Device
{
@@ -83,9 +112,6 @@ public sealed class Device : Devices.Device
dev.Type = DeviceType.Unknown;
dev.ScsiType = PeripheralDeviceTypes.UnknownDevice;
- byte[] ataBuf;
- byte[] inqBuf = null;
-
if(dev.Error)
throw new DeviceException(dev.LastError);
@@ -93,11 +119,6 @@ public sealed class Device : Devices.Device
switch(dev.Type)
{
- case DeviceType.ATAPI:
- case DeviceType.SCSI:
- bool scsiSense = dev.ScsiInquiry(out inqBuf, out _);
-
- break;
case DeviceType.SecureDigital:
case DeviceType.MMC:
if(!dev._remote.GetSdhciRegisters(out dev._cachedCsd, out dev._cachedCid, out dev._cachedOcr,
diff --git a/Aaru.Devices/Windows/Command.cs b/Aaru.Devices/Windows/Command.cs
index 5a6711b3f..1f1896e4c 100644
--- a/Aaru.Devices/Windows/Command.cs
+++ b/Aaru.Devices/Windows/Command.cs
@@ -40,24 +40,16 @@ using Aaru.Decoders.ATA;
using Microsoft.Win32.SafeHandles;
[SuppressMessage("ReSharper", "UnusedParameter.Global")]
-static class Command
+partial class Device
{
- /// Sends a SCSI command
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// SCSI CDB
- /// Buffer for SCSI command response
- /// Buffer with the SCSI sense
- /// Timeout in seconds
- /// SCSI command transfer direction
- /// Time it took to execute the command in milliseconds
- ///
- /// True if SCSI error returned non-OK status and contains SCSI
- /// 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)
+ ///
+ public override int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
+ ScsiDirection direction, out double duration, out bool sense)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
senseBuffer = null;
duration = 0;
sense = false;
@@ -65,6 +57,24 @@ static class Command
if(buffer == null)
return -1;
+ ScsiIoctlDirection dir;
+
+ switch(direction)
+ {
+ case ScsiDirection.In:
+ dir = ScsiIoctlDirection.In;
+
+ break;
+ case ScsiDirection.Out:
+ dir = ScsiIoctlDirection.Out;
+
+ break;
+ default:
+ dir = ScsiIoctlDirection.Unspecified;
+
+ break;
+ }
+
var sptdSb = new ScsiPassThroughDirectAndSenseBuffer
{
SenseBuf = new byte[32],
@@ -73,7 +83,7 @@ static class Command
Cdb = new byte[16],
CdbLength = (byte)cdb.Length,
SenseInfoLength = 32,
- DataIn = direction,
+ DataIn = dir,
DataTransferLength = (uint)buffer.Length,
TimeOutValue = timeout,
DataBuffer = Marshal.AllocHGlobal(buffer.Length)
@@ -91,7 +101,7 @@ static class Command
DateTime start = DateTime.Now;
- bool hasError = !Extern.DeviceIoControlScsi(fd, WindowsIoctl.IoctlScsiPassThroughDirect, ref sptdSb,
+ bool hasError = !Extern.DeviceIoControlScsi(_fileHandle, WindowsIoctl.IoctlScsiPassThroughDirect, ref sptdSb,
(uint)Marshal.SizeOf(sptdSb), ref sptdSb,
(uint)Marshal.SizeOf(sptdSb), ref k, IntPtr.Zero);
@@ -114,20 +124,15 @@ static class Command
return error;
}
- /// Sends an ATA command in CHS mode
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA error returned non-OK status
- /// Registers to send to drive
- /// Registers returned by drive
- /// ATA protocol to use
- internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersChs registers,
- out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, ref byte[] buffer,
- uint timeout, out double duration, out bool sense)
+ ///
+ public override int SendAtaCommand(AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
duration = 0;
sense = false;
errorRegisters = new AtaErrorRegistersChs();
@@ -191,7 +196,7 @@ static class Command
DateTime start = DateTime.Now;
- sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThroughDirect, ref aptd,
+ sense = !Extern.DeviceIoControlAta(_fileHandle, WindowsIoctl.IoctlAtaPassThroughDirect, ref aptd,
(uint)Marshal.SizeOf(aptd), ref aptd, (uint)Marshal.SizeOf(aptd), ref k,
IntPtr.Zero);
@@ -219,20 +224,15 @@ static class Command
return error;
}
- /// Sends an ATA command in 28-bit LBA mode
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA error returned non-OK status
- /// Registers to send to drive
- /// Registers returned by drive
- /// ATA protocol to use
- internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba28 registers,
- out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
- ref byte[] buffer, uint timeout, out double duration, out bool sense)
+ ///
+ public override int SendAtaCommand(AtaRegistersLba28 registers, out AtaErrorRegistersLba28 errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
duration = 0;
sense = false;
errorRegisters = new AtaErrorRegistersLba28();
@@ -296,7 +296,7 @@ static class Command
DateTime start = DateTime.Now;
- sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThroughDirect, ref aptd,
+ sense = !Extern.DeviceIoControlAta(_fileHandle, WindowsIoctl.IoctlAtaPassThroughDirect, ref aptd,
(uint)Marshal.SizeOf(aptd), ref aptd, (uint)Marshal.SizeOf(aptd), ref k,
IntPtr.Zero);
@@ -324,20 +324,15 @@ static class Command
return error;
}
- /// Sends an ATA command in 48-bit LBA mode
- /// 0 if no error occurred, otherwise, errno
- /// File handle
- /// Buffer for SCSI command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if ATA error returned non-OK status
- /// Registers to send to drive
- /// Registers returned by drive
- /// ATA protocol to use
- internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba48 registers,
- out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
- ref byte[] buffer, uint timeout, out double duration, out bool sense)
+ ///
+ public override int SendAtaCommand(AtaRegistersLba48 registers, out AtaErrorRegistersLba48 errorRegisters,
+ AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer,
+ uint timeout, bool transferBlocks, out double duration, out bool sense)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
duration = 0;
sense = false;
errorRegisters = new AtaErrorRegistersLba48();
@@ -410,7 +405,7 @@ static class Command
DateTime start = DateTime.Now;
- sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThroughDirect, ref aptd,
+ sense = !Extern.DeviceIoControlAta(_fileHandle, WindowsIoctl.IoctlAtaPassThroughDirect, ref aptd,
(uint)Marshal.SizeOf(aptd), ref aptd, (uint)Marshal.SizeOf(aptd), ref k,
IntPtr.Zero);
@@ -458,25 +453,67 @@ static class Command
queryData1.protocolGuid.Equals(Consts.GuidSffProtocolMmc);
}
- /// Sends a MMC/SD command
- /// The result of the command.
- /// File handle
- /// MMC/SD opcode
- /// Buffer for MMC/SD command response
- /// Timeout in seconds
- /// Time it took to execute the command in milliseconds
- /// True if MMC/SD returned non-OK status
- /// True if data is sent from host to card
- /// True if command should be preceded with CMD55
- /// Flags indicating kind and place of response
- /// How many blocks to transfer
- /// Command argument
- /// Response registers
- /// Size of block in bytes
- 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)
+ ///
+ public override 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 = 15)
{
+ DateTime start;
+ DateTime end;
+
+ switch(command)
+ {
+ case MmcCommands.SendCid when _cachedCid != null:
+ {
+ start = DateTime.Now;
+ buffer = new byte[_cachedCid.Length];
+ Array.Copy(_cachedCid, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case MmcCommands.SendCsd when _cachedCid != null:
+ {
+ start = DateTime.Now;
+ buffer = new byte[_cachedCsd.Length];
+ Array.Copy(_cachedCsd, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case (MmcCommands)SecureDigitalCommands.SendScr when _cachedScr != null:
+ {
+ start = DateTime.Now;
+ buffer = new byte[_cachedScr.Length];
+ Array.Copy(_cachedScr, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ case (MmcCommands)SecureDigitalCommands.SendOperatingCondition when _cachedOcr != null:
+ case MmcCommands.SendOpCond when _cachedOcr != null:
+ {
+ start = DateTime.Now;
+ buffer = new byte[_cachedOcr.Length];
+ Array.Copy(_cachedOcr, buffer, buffer.Length);
+ response = new uint[4];
+ sense = false;
+ end = DateTime.Now;
+ duration = (end - start).TotalMilliseconds;
+
+ return 0;
+ }
+ }
+
var commandData = new SffdiskDeviceCommandData();
var commandDescriptor = new SdCmdDescriptor();
commandData.size = (ushort)Marshal.SizeOf(commandData);
@@ -531,13 +568,13 @@ static class Command
Marshal.Copy(hBuf, commandB, 0, commandB.Length);
Marshal.FreeHGlobal(hBuf);
- var error = 0;
- DateTime start = DateTime.Now;
+ var error = 0;
+ start = DateTime.Now;
- sense = !Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskDeviceCommand, commandB, (uint)commandB.Length,
- commandB, (uint)commandB.Length, out _, IntPtr.Zero);
+ sense = !Extern.DeviceIoControl(_fileHandle, WindowsIoctl.IoctlSffdiskDeviceCommand, commandB,
+ (uint)commandB.Length, commandB, (uint)commandB.Length, out _, IntPtr.Zero);
- DateTime end = DateTime.Now;
+ end = DateTime.Now;
if(sense)
error = Marshal.GetLastWin32Error();
@@ -551,9 +588,14 @@ static class Command
return error;
}
- internal static int SendMultipleMmcCommands(SafeFileHandle fd, Device.MmcSingleCommand[] commands,
- out double duration, out bool sense, uint timeout = 0)
+ ///
+ public override int SendMultipleMmcCommands(MmcSingleCommand[] commands, out double duration, out bool sense,
+ uint timeout = 15)
{
+ // We need a timeout
+ if(timeout == 0)
+ timeout = Timeout > 0 ? Timeout : 15;
+
var error = 0;
duration = 0;
sense = false;
@@ -562,13 +604,13 @@ static class Command
commands[0].command == MmcCommands.SetBlocklen &&
commands[1].command == MmcCommands.ReadMultipleBlock &&
commands[2].command == MmcCommands.StopTransmission)
- return SendMmcCommand(fd, commands[1].command, commands[1].write, commands[1].isApplication,
- commands[1].flags, commands[1].argument, commands[1].blockSize, commands[1].blocks,
+ return SendMmcCommand(commands[1].command, commands[1].write, commands[1].isApplication, commands[1].flags,
+ commands[1].argument, commands[1].blockSize, commands[1].blocks,
ref commands[1].buffer, out commands[1].response, out duration, out sense, timeout);
- foreach(Device.MmcSingleCommand command in commands)
+ foreach(MmcSingleCommand command in commands)
{
- int singleError = SendMmcCommand(fd, command.command, command.write, command.isApplication, command.flags,
+ int singleError = SendMmcCommand(command.command, command.write, command.isApplication, command.flags,
command.argument, command.blockSize, command.blocks, ref command.buffer,
out command.response, out double cmdDuration, out bool cmdSense, timeout);
@@ -585,25 +627,36 @@ static class Command
return error;
}
- internal static int ReOpen(string devicePath, SafeFileHandle fd, out object newFd)
+ ///
+ public override bool ReOpen()
{
- Extern.CloseHandle(fd);
+ Extern.CloseHandle(_fileHandle);
- newFd = Extern.CreateFile(devicePath, FileAccess.GenericRead | FileAccess.GenericWrite,
- FileShare.Read | FileShare.Write, IntPtr.Zero, FileMode.OpenExisting,
- FileAttributes.Normal, IntPtr.Zero);
+ SafeFileHandle newFd = Extern.CreateFile(_devicePath, FileAccess.GenericRead | FileAccess.GenericWrite,
+ FileShare.Read | FileShare.Write, IntPtr.Zero, FileMode.OpenExisting,
+ FileAttributes.Normal, IntPtr.Zero);
- return ((SafeFileHandle)newFd).IsInvalid ? Marshal.GetLastWin32Error() : 0;
+ if(newFd.IsInvalid)
+ {
+ LastError = Marshal.GetLastWin32Error();
+ Error = true;
+
+ return true;
+ }
+
+ _fileHandle = newFd;
+
+ return false;
}
- internal static int BufferedOsRead(SafeFileHandle fd, out byte[] buffer, long offset, uint length,
- out double duration)
+ ///
+ public override bool BufferedOsRead(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);
+ bool sense = !Extern.SetFilePointerEx(_fileHandle, offset, out _, MoveMethod.Begin);
DateTime end = DateTime.Now;
@@ -611,14 +664,27 @@ static class Command
{
duration = (end - start).TotalMilliseconds;
- return Marshal.GetLastWin32Error();
+ LastError = Marshal.GetLastWin32Error();
+ Error = true;
+
+ return true;
}
- sense = !Extern.ReadFile(fd, buffer, length, out _, IntPtr.Zero);
+ sense = !Extern.ReadFile(_fileHandle, buffer, length, out _, IntPtr.Zero);
end = DateTime.Now;
duration = (end - start).TotalMilliseconds;
- return sense ? Marshal.GetLastWin32Error() : 0;
+ if(sense)
+ {
+ Error = true;
+ LastError = Marshal.GetLastWin32Error();
+
+ return true;
+ }
+
+ Error = false;
+
+ return false;
}
}
\ No newline at end of file
diff --git a/Aaru.Devices/Windows/Device.cs b/Aaru.Devices/Windows/Device.cs
index b2edaeece..64b74dcad 100644
--- a/Aaru.Devices/Windows/Device.cs
+++ b/Aaru.Devices/Windows/Device.cs
@@ -43,25 +43,28 @@ using Microsoft.Win32.SafeHandles;
///
[SupportedOSPlatform("windows")]
-public class Device : Devices.Device
+partial class Device : Devices.Device
{
+ /// Gets the file handle representing this device
+ /// The file handle
+ SafeFileHandle _fileHandle;
+
Device() {}
- public new static Device Create(string devicePath)
+ internal new static Device Create(string devicePath)
{
var dev = new Device
{
- PlatformId = DetectOS.GetRealPlatformID(),
- Timeout = 15,
- Error = false,
- IsRemovable = false
+ PlatformId = DetectOS.GetRealPlatformID(),
+ Timeout = 15,
+ Error = false,
+ IsRemovable = false,
+ _fileHandle = Extern.CreateFile(devicePath, FileAccess.GenericRead | FileAccess.GenericWrite,
+ FileShare.Read | FileShare.Write, IntPtr.Zero, FileMode.OpenExisting,
+ FileAttributes.Normal, IntPtr.Zero)
};
- dev.FileHandle = Extern.CreateFile(devicePath, FileAccess.GenericRead | FileAccess.GenericWrite,
- FileShare.Read | FileShare.Write, IntPtr.Zero, FileMode.OpenExisting,
- FileAttributes.Normal, IntPtr.Zero);
-
- if(((SafeFileHandle)dev.FileHandle).IsInvalid)
+ if(dev._fileHandle.IsInvalid)
{
dev.Error = true;
dev.LastError = Marshal.GetLastWin32Error();
@@ -73,9 +76,6 @@ public class Device : Devices.Device
dev.Type = DeviceType.Unknown;
dev.ScsiType = PeripheralDeviceTypes.UnknownDevice;
- byte[] ataBuf;
- byte[] inqBuf = null;
-
if(dev.Error)
throw new DeviceException(dev.LastError);
@@ -91,9 +91,8 @@ public class Device : Devices.Device
uint returned = 0;
var error = 0;
- bool hasError = !Extern.DeviceIoControlStorageQuery((SafeFileHandle)dev.FileHandle,
- WindowsIoctl.IoctlStorageQueryProperty, ref query,
- (uint)Marshal.SizeOf(query), descriptorPtr, 1000,
+ bool hasError = !Extern.DeviceIoControlStorageQuery(dev._fileHandle, WindowsIoctl.IoctlStorageQueryProperty,
+ ref query, (uint)Marshal.SizeOf(query), descriptorPtr, 1000,
ref returned, IntPtr.Zero);
if(hasError)
@@ -170,7 +169,7 @@ public class Device : Devices.Device
switch(dev.Type)
{
case DeviceType.ATA:
- bool atapiSense = dev.AtapiIdentify(out ataBuf, out _);
+ bool atapiSense = dev.AtapiIdentify(out byte[] _, out _);
if(!atapiSense)
dev.Type = DeviceType.ATAPI;
@@ -183,13 +182,13 @@ public class Device : Devices.Device
Marshal.FreeHGlobal(descriptorPtr);
- if(Command.IsSdhci((SafeFileHandle)dev.FileHandle))
+ if(IsSdhci(dev._fileHandle))
{
var sdBuffer = new byte[16];
- dev.LastError = Command.SendMmcCommand((SafeFileHandle)dev.FileHandle, MmcCommands.SendCsd, false, false,
- MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 | MmcFlags.CommandAc, 0,
- 16, 1, ref sdBuffer, out _, out _, out bool sense);
+ dev.LastError = dev.SendMmcCommand(MmcCommands.SendCsd, false, false,
+ MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 | MmcFlags.CommandAc, 0, 16,
+ 1, ref sdBuffer, out _, out _, out bool sense);
if(!sense)
{
@@ -199,9 +198,9 @@ public class Device : Devices.Device
sdBuffer = new byte[16];
- dev.LastError = Command.SendMmcCommand((SafeFileHandle)dev.FileHandle, MmcCommands.SendCid, false, false,
- MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 | MmcFlags.CommandAc, 0,
- 16, 1, ref sdBuffer, out _, out _, out sense);
+ dev.LastError = dev.SendMmcCommand(MmcCommands.SendCid, false, false,
+ MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 | MmcFlags.CommandAc, 0, 16,
+ 1, ref sdBuffer, out _, out _, out sense);
if(!sense)
{
@@ -211,10 +210,9 @@ public class Device : Devices.Device
sdBuffer = new byte[8];
- dev.LastError = Command.SendMmcCommand((SafeFileHandle)dev.FileHandle,
- (MmcCommands)SecureDigitalCommands.SendScr, false, true,
- MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc,
- 0, 8, 1, ref sdBuffer, out _, out _, out sense);
+ dev.LastError = dev.SendMmcCommand((MmcCommands)SecureDigitalCommands.SendScr, false, true,
+ MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 | MmcFlags.CommandAdtc, 0,
+ 8, 1, ref sdBuffer, out _, out _, out sense);
if(!sense)
{
@@ -224,12 +222,10 @@ public class Device : Devices.Device
sdBuffer = new byte[4];
- dev.LastError = Command.SendMmcCommand((SafeFileHandle)dev.FileHandle,
- dev._cachedScr != null
- ? (MmcCommands)SecureDigitalCommands.SendOperatingCondition
- : MmcCommands.SendOpCond, false, true,
- MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 | MmcFlags.CommandBcr,
- 0, 4, 1, ref sdBuffer, out _, out _, out sense);
+ dev.LastError =
+ dev.SendMmcCommand(dev._cachedScr != null ? (MmcCommands)SecureDigitalCommands.SendOperatingCondition : MmcCommands.SendOpCond,
+ false, true, MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 | MmcFlags.CommandBcr, 0,
+ 4, 1, ref sdBuffer, out _, out _, out sense);
if(!sense)
{
@@ -318,11 +314,11 @@ public class Device : Devices.Device
///
public override void Close()
{
- if(FileHandle == null)
+ if(_fileHandle == null)
return;
- (FileHandle as SafeFileHandle)?.Close();
+ _fileHandle?.Close();
- FileHandle = null;
+ _fileHandle = null;
}
}
\ No newline at end of file
diff --git a/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs b/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs
index f441e7f12..3bfb0b902 100644
--- a/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs
@@ -250,10 +250,11 @@ public sealed class MainWindowViewModel : ViewModelBase
{
var dev = Device.Create(deviceModel.Path);
- if(dev.IsRemote)
- Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion,
- dev.RemoteOperatingSystem, dev.RemoteOperatingSystemVersion,
- dev.RemoteArchitecture);
+ if(dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
+ remoteDev.RemoteOperatingSystem,
+ remoteDev.RemoteOperatingSystemVersion,
+ remoteDev.RemoteArchitecture);
if(dev.Error)
{
@@ -789,9 +790,10 @@ public sealed class MainWindowViewModel : ViewModelBase
{
var dev = Device.Create(device.Path);
- if(dev.IsRemote)
- Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
- dev.RemoteOperatingSystemVersion, dev.RemoteArchitecture);
+ if(dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
+ remoteDev.RemoteOperatingSystem, remoteDev.RemoteOperatingSystemVersion,
+ remoteDev.RemoteArchitecture);
switch(dev.Type)
{
diff --git a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
index 89602b321..09343e81f 100644
--- a/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/MediaDumpViewModel.cs
@@ -728,9 +728,10 @@ public sealed class MediaDumpViewModel : ViewModelBase
{
_dev = Device.Create(_devicePath);
- if(_dev.IsRemote)
- Statistics.AddRemote(_dev.RemoteApplication, _dev.RemoteVersion, _dev.RemoteOperatingSystem,
- _dev.RemoteOperatingSystemVersion, _dev.RemoteArchitecture);
+ if(_dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
+ remoteDev.RemoteOperatingSystem, remoteDev.RemoteOperatingSystemVersion,
+ remoteDev.RemoteArchitecture);
if(_dev.Error)
{
diff --git a/Aaru.Gui/ViewModels/Windows/MediaScanViewModel.cs b/Aaru.Gui/ViewModels/Windows/MediaScanViewModel.cs
index 71aa1e434..4847fcdea 100644
--- a/Aaru.Gui/ViewModels/Windows/MediaScanViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/MediaScanViewModel.cs
@@ -330,9 +330,9 @@ public sealed class MediaScanViewModel : ViewModelBase
var dev = Device.Create(_devicePath);
- if(dev.IsRemote)
- Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
- dev.RemoteOperatingSystemVersion, dev.RemoteArchitecture);
+ if(dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion, remoteDev.RemoteOperatingSystem,
+ remoteDev.RemoteOperatingSystemVersion, remoteDev.RemoteArchitecture);
if(dev.Error)
{
diff --git a/Aaru.Tests.Devices/Device.cs b/Aaru.Tests.Devices/Device.cs
index e7e0dfd00..27a8518f2 100644
--- a/Aaru.Tests.Devices/Device.cs
+++ b/Aaru.Tests.Devices/Device.cs
@@ -44,7 +44,6 @@ static partial class MainClass
while(true)
{
AaruConsole.WriteLine("dev.PlatformID = {0}", dev.PlatformId);
- AaruConsole.WriteLine("dev.FileHandle = {0}", dev.FileHandle);
AaruConsole.WriteLine("dev.Timeout = {0}", dev.Timeout);
AaruConsole.WriteLine("dev.Error = {0}", dev.Error);
AaruConsole.WriteLine("dev.LastError = {0}", dev.LastError);
diff --git a/Aaru/Commands/Device/DeviceReport.cs b/Aaru/Commands/Device/DeviceReport.cs
index f5c01bbec..894608b17 100644
--- a/Aaru/Commands/Device/DeviceReport.cs
+++ b/Aaru/Commands/Device/DeviceReport.cs
@@ -130,9 +130,10 @@ sealed class DeviceReportCommand : Command
{
dev = Device.Create(devicePath);
- if(dev.IsRemote)
- Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
- dev.RemoteOperatingSystemVersion, dev.RemoteArchitecture);
+ if(dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
+ remoteDev.RemoteOperatingSystem, remoteDev.RemoteOperatingSystemVersion,
+ remoteDev.RemoteArchitecture);
if(dev.Error)
{
@@ -150,7 +151,7 @@ sealed class DeviceReportCommand : Command
Statistics.AddDevice(dev);
- bool isAdmin = dev.IsRemote ? dev.IsRemoteAdmin : DetectOS.IsAdmin;
+ bool isAdmin = dev is Devices.Remote.Device remoteDev2 ? remoteDev2.IsAdmin : DetectOS.IsAdmin;
if(!isAdmin)
{
diff --git a/Aaru/Commands/Device/Info.cs b/Aaru/Commands/Device/Info.cs
index 058eafd7e..415784a66 100644
--- a/Aaru/Commands/Device/Info.cs
+++ b/Aaru/Commands/Device/Info.cs
@@ -134,9 +134,10 @@ sealed class DeviceInfoCommand : Command
{
dev = Device.Create(devicePath);
- if(dev.IsRemote)
- Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
- dev.RemoteOperatingSystemVersion, dev.RemoteArchitecture);
+ if(dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
+ remoteDev.RemoteOperatingSystem, remoteDev.RemoteOperatingSystemVersion,
+ remoteDev.RemoteArchitecture);
if(dev.Error)
{
diff --git a/Aaru/Commands/Media/Dump.cs b/Aaru/Commands/Media/Dump.cs
index 739f06a27..69bce71ba 100644
--- a/Aaru/Commands/Media/Dump.cs
+++ b/Aaru/Commands/Media/Dump.cs
@@ -546,9 +546,10 @@ sealed class DumpMediaCommand : Command
dev = Device.Create(devicePath);
});
- if(dev.IsRemote)
- Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
- dev.RemoteOperatingSystemVersion, dev.RemoteArchitecture);
+ if(dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
+ remoteDev.RemoteOperatingSystem, remoteDev.RemoteOperatingSystemVersion,
+ remoteDev.RemoteArchitecture);
if(dev.Error)
{
diff --git a/Aaru/Commands/Media/Info.cs b/Aaru/Commands/Media/Info.cs
index d158ab608..708e24786 100644
--- a/Aaru/Commands/Media/Info.cs
+++ b/Aaru/Commands/Media/Info.cs
@@ -139,9 +139,10 @@ sealed class MediaInfoCommand : Command
dev = Device.Create(devicePath);
});
- if(dev.IsRemote)
- Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
- dev.RemoteOperatingSystemVersion, dev.RemoteArchitecture);
+ if(dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
+ remoteDev.RemoteOperatingSystem, remoteDev.RemoteOperatingSystemVersion,
+ remoteDev.RemoteArchitecture);
if(dev.Error)
{
diff --git a/Aaru/Commands/Media/Scan.cs b/Aaru/Commands/Media/Scan.cs
index 5e08d5a70..0c8b5bebc 100644
--- a/Aaru/Commands/Media/Scan.cs
+++ b/Aaru/Commands/Media/Scan.cs
@@ -140,9 +140,10 @@ sealed class MediaScanCommand : Command
dev = Device.Create(devicePath);
});
- if(dev.IsRemote)
- Statistics.AddRemote(dev.RemoteApplication, dev.RemoteVersion, dev.RemoteOperatingSystem,
- dev.RemoteOperatingSystemVersion, dev.RemoteArchitecture);
+ if(dev is Devices.Remote.Device remoteDev)
+ Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
+ remoteDev.RemoteOperatingSystem, remoteDev.RemoteOperatingSystemVersion,
+ remoteDev.RemoteArchitecture);
if(dev.Error)
{