2020-03-11 21:56:55 +00:00
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Remote.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Aaru Remote.
//
// --[ Description ] ----------------------------------------------------------
//
// Implementation of the Aaru Remote protocol.
//
// --[ 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 <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
2020-12-31 23:08:23 +00:00
// Copyright © 2011-2021 Natalia Portillo
2020-03-11 21:56:55 +00:00
// ****************************************************************************/
2019-10-12 22:51:50 +01:00
using System ;
2019-10-12 23:44:51 +01:00
using System.Collections.Generic ;
2019-10-12 22:51:50 +01:00
using System.IO ;
using System.Linq ;
using System.Net ;
using System.Net.Sockets ;
2019-10-12 23:44:51 +01:00
using System.Runtime.InteropServices ;
2020-02-27 00:33:26 +00:00
using Aaru.CommonTypes.Enums ;
using Aaru.CommonTypes.Interop ;
using Aaru.Console ;
using Aaru.Decoders.ATA ;
using Marshal = Aaru . Helpers . Marshal ;
using Version = Aaru . CommonTypes . Interop . Version ;
2021-08-17 13:56:05 +01:00
// ReSharper disable MemberCanBeInternal
2019-10-12 22:51:50 +01:00
2020-02-27 00:33:26 +00:00
namespace Aaru.Devices.Remote
2019-10-12 22:51:50 +01:00
{
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
/// <summary>
/// Handles communication with a remote device that's connected using the AaruRemote protocol
/// </summary>
2019-10-12 23:12:39 +01:00
public class Remote : IDisposable
2019-10-12 22:51:50 +01:00
{
2020-02-29 18:03:35 +00:00
readonly string _host ;
readonly Socket _socket ;
2019-10-12 22:51:50 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Connects using TCP/IP to the specified remote
/// </summary>
/// <param name="uri">URI of the remote</param>
/// <exception cref="ArgumentException">Unsupported or invalid remote protocol.</exception>
/// <exception cref="SocketException">Host not found.</exception>
/// <exception cref="IOException">Network error.</exception>
2021-06-22 20:23:21 +01:00
public Remote ( Uri uri )
2019-10-12 22:51:50 +01:00
{
2021-06-22 20:23:21 +01:00
if ( uri . Scheme ! = "aaru" & &
uri . Scheme ! = "dic" )
throw new ArgumentException ( "Invalid remote protocol." , nameof ( uri . Scheme ) ) ;
2019-10-12 22:51:50 +01:00
2021-06-22 20:23:21 +01:00
_host = uri . DnsSafeHost ;
if ( ! IPAddress . TryParse ( _host , out IPAddress ipAddress ) )
2020-10-17 00:19:57 +01:00
{
2021-06-22 20:23:21 +01:00
IPHostEntry ipHostEntry = Dns . GetHostEntry ( _host ) ;
2020-10-17 00:19:57 +01:00
ipAddress = ipHostEntry . AddressList . FirstOrDefault ( a = > a . AddressFamily = = AddressFamily . InterNetwork ) ;
}
2020-02-29 18:03:35 +00:00
if ( ipAddress is null )
2019-10-12 22:51:50 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Host not found" ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 22:51:50 +01:00
throw new SocketException ( 11001 ) ;
}
2021-06-22 20:23:21 +01:00
var ipEndPoint = new IPEndPoint ( ipAddress , uri . Port > 0 ? uri . Port : 6666 ) ;
2019-10-12 22:51:50 +01:00
_socket = new Socket ( AddressFamily . InterNetwork , SocketType . Stream , ProtocolType . Tcp ) ;
_socket . Connect ( ipEndPoint ) ;
2021-06-22 20:23:21 +01:00
AaruConsole . WriteLine ( "Connected to {0}" , uri . Host ) ;
2019-10-12 22:51:50 +01:00
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-12 22:51:50 +01:00
2020-02-29 18:03:35 +00:00
int len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-12 22:51:50 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-12 22:51:50 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 22:51:50 +01:00
throw new IOException ( ) ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-12 22:51:50 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-12 22:51:50 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 22:51:50 +01:00
throw new ArgumentException ( ) ;
}
2019-10-13 20:54:10 +01:00
byte [ ] buf ;
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . Hello )
2019-10-12 22:51:50 +01:00
{
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . Nop )
2019-10-13 20:54:10 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected Hello Packet, got packet type {0}..." , hdr . packetType ) ;
2020-02-29 18:03:35 +00:00
2019-10-13 20:54:10 +01:00
throw new ArgumentException ( ) ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-13 20:54:10 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-13 20:54:10 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-13 20:54:10 +01:00
throw new IOException ( ) ;
}
2020-02-29 18:03:35 +00:00
AaruPacketNop nop = Marshal . ByteArrayToStructureLittleEndian < AaruPacketNop > ( buf ) ;
2019-10-13 20:54:10 +01:00
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( $"{nop.reason}" ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 22:51:50 +01:00
throw new ArgumentException ( ) ;
}
2020-07-20 21:11:32 +01:00
if ( hdr . version ! = Consts . PACKET_VERSION )
2019-10-12 22:51:50 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Unrecognized packet version..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 22:51:50 +01:00
throw new ArgumentException ( ) ;
}
2019-10-13 20:54:10 +01:00
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-12 22:51:50 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-12 22:51:50 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 22:51:50 +01:00
throw new IOException ( ) ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHello serverHello = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHello > ( buf ) ;
2019-10-12 22:51:50 +01:00
2020-02-29 18:03:35 +00:00
ServerApplication = serverHello . application ;
ServerVersion = serverHello . version ;
ServerOperatingSystem = serverHello . sysname ;
2019-10-12 22:51:50 +01:00
ServerOperatingSystemVersion = serverHello . release ;
2020-02-29 18:03:35 +00:00
ServerArchitecture = serverHello . machine ;
ServerProtocolVersion = serverHello . maxProtocol ;
2019-10-12 22:51:50 +01:00
2020-02-27 22:42:21 +00:00
var clientHello = new AaruPacketHello
2019-10-12 22:51:50 +01:00
{
2020-07-20 04:34:16 +01:00
application = "Aaru" ,
version = Version . GetVersion ( ) ,
2020-07-20 21:11:32 +01:00
maxProtocol = Consts . MAX_PROTOCOL ,
2020-02-29 18:03:35 +00:00
sysname = DetectOS . GetPlatformName ( DetectOS . GetRealPlatformID ( ) , DetectOS . GetVersion ( ) ) ,
2020-07-20 04:34:16 +01:00
release = DetectOS . GetVersion ( ) ,
machine = RuntimeInformation . ProcessArchitecture . ToString ( ) ,
hdr = new AaruPacketHeader
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketHello > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-07-20 04:34:16 +01:00
packetType = AaruPacketType . Hello
}
2019-10-12 22:51:50 +01:00
} ;
buf = Marshal . StructureToByteArrayLittleEndian ( clientHello ) ;
len = _socket . Send ( buf , SocketFlags . None ) ;
2020-02-29 18:03:35 +00:00
if ( len > = buf . Length )
return ;
2019-10-12 22:51:50 +01:00
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 22:51:50 +01:00
throw new IOException ( ) ;
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Remote server application
/// </summary>
2020-02-29 18:03:35 +00:00
public string ServerApplication { get ; }
2021-08-17 13:56:05 +01:00
/// <summary>
/// Remote server application version
/// </summary>
2020-02-29 18:03:35 +00:00
public string ServerVersion { get ; }
2021-08-17 13:56:05 +01:00
/// <summary>
/// Remote server operating system
/// </summary>
2020-02-29 18:03:35 +00:00
public string ServerOperatingSystem { get ; }
2021-08-17 13:56:05 +01:00
/// <summary>
/// Remote server operating system version
/// </summary>
2019-10-12 22:51:50 +01:00
public string ServerOperatingSystemVersion { get ; }
2021-08-17 13:56:05 +01:00
/// <summary>
/// Remote server architecture
/// </summary>
2020-02-29 18:03:35 +00:00
public string ServerArchitecture { get ; }
2021-08-17 13:56:05 +01:00
/// <summary>
/// Remote server protocol version
/// </summary>
2020-02-29 18:03:35 +00:00
public int ServerProtocolVersion { get ; }
2019-10-12 22:51:50 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Is remote running with administrative (aka root) privileges?
/// </summary>
2019-10-26 17:39:50 +01:00
public bool IsRoot
{
get
{
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdAmIRoot
2019-10-26 17:39:50 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-26 17:39:50 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCmdAmIRoot > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandAmIRoot
2019-10-26 17:39:50 +01:00
}
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-26 17:39:50 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-26 17:39:50 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-26 17:39:50 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-26 17:39:50 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-26 17:39:50 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-26 17:39:50 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-26 17:39:50 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-26 17:39:50 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-26 17:39:50 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-26 17:39:50 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseAmIRoot )
2019-10-26 17:39:50 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected Am I Root? Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-26 17:39:50 +01:00
return false ;
}
buf = new byte [ hdr . len ] ;
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-26 17:39:50 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-26 17:39:50 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResAmIRoot res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResAmIRoot > ( buf ) ;
2019-10-26 17:39:50 +01:00
2019-11-01 01:10:34 +00:00
return res . am_i_root ! = 0 ;
2019-10-26 17:39:50 +01:00
}
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-02-29 18:03:35 +00:00
public void Dispose ( ) = > Disconnect ( ) ;
2019-10-12 23:12:39 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Disconnects from remote
/// </summary>
2019-10-12 22:51:50 +01:00
public void Disconnect ( )
{
2020-10-17 00:19:31 +01:00
try
{
_socket . Shutdown ( SocketShutdown . Both ) ;
_socket . Close ( ) ;
}
catch ( ObjectDisposedException )
{
// Ignore if already disposed
}
2019-10-12 22:51:50 +01:00
}
2019-10-12 23:12:39 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Lists devices attached to remote
/// </summary>
/// <returns>List of devices</returns>
2019-10-12 23:12:39 +01:00
public DeviceInfo [ ] ListDevices ( )
{
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCommandListDevices
2019-10-12 23:23:33 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-12 23:23:33 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCommandListDevices > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandListDevices
2019-10-12 23:23:33 +01:00
}
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-12 23:23:33 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-12 23:23:33 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-12 23:23:33 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2019-10-12 23:23:33 +01:00
return new DeviceInfo [ 0 ] ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-12 23:44:51 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-12 23:44:51 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-12 23:44:51 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 23:44:51 +01:00
return new DeviceInfo [ 0 ] ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-12 23:44:51 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-12 23:44:51 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 23:44:51 +01:00
return new DeviceInfo [ 0 ] ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseListDevices )
2019-10-12 23:44:51 +01:00
{
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . Nop )
2019-10-13 20:54:10 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected List Devices Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-13 20:54:10 +01:00
return new DeviceInfo [ 0 ] ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-13 20:54:10 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-13 20:54:10 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-13 20:54:10 +01:00
return new DeviceInfo [ 0 ] ;
}
2020-02-29 18:03:35 +00:00
AaruPacketNop nop = Marshal . ByteArrayToStructureLittleEndian < AaruPacketNop > ( buf ) ;
2019-10-13 20:54:10 +01:00
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( $"{nop.reason}" ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 23:44:51 +01:00
return new DeviceInfo [ 0 ] ;
}
2020-07-20 21:11:32 +01:00
if ( hdr . version ! = Consts . PACKET_VERSION )
2019-10-12 23:44:51 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Unrecognized packet version..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 23:44:51 +01:00
return new DeviceInfo [ 0 ] ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-12 23:44:51 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-12 23:44:51 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-12 23:44:51 +01:00
return new DeviceInfo [ 0 ] ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResponseListDevices response =
Marshal . ByteArrayToStructureLittleEndian < AaruPacketResponseListDevices > ( buf ) ;
List < DeviceInfo > devices = new List < DeviceInfo > ( ) ;
int offset = Marshal . SizeOf < AaruPacketResponseListDevices > ( ) ;
int devInfoLen = Marshal . SizeOf < DeviceInfo > ( ) ;
2019-10-12 23:44:51 +01:00
2020-02-29 18:03:35 +00:00
for ( ushort i = 0 ; i < response . devices ; i + + )
2019-10-12 23:44:51 +01:00
{
2020-02-29 18:03:35 +00:00
DeviceInfo dev = Marshal . ByteArrayToStructureLittleEndian < DeviceInfo > ( buf , offset , devInfoLen ) ;
2020-03-01 06:02:40 +00:00
dev . Path = dev . Path [ 0 ] = = '/' ? $"aaru://{_host}{dev.Path}" : $"aaru://{_host}/{dev.Path}" ;
2019-10-13 15:13:36 +01:00
devices . Add ( dev ) ;
2019-10-12 23:44:51 +01:00
offset + = devInfoLen ;
}
return devices . ToArray ( ) ;
2019-10-12 23:12:39 +01:00
}
2019-10-13 22:29:09 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Opens the specified device path on the remote
/// </summary>
/// <param name="devicePath">Device path</param>
/// <param name="lastError">Returned error</param>
/// <returns><c>true</c> if opened correctly, <c>false</c>otherwise</returns>
/// <exception cref="NotImplementedException">Support for the specified device has not yet been implemented in the remote application.</exception>
2019-10-19 18:28:05 +01:00
public bool Open ( string devicePath , out int lastError )
2019-10-13 22:29:09 +01:00
{
2019-10-19 18:28:05 +01:00
lastError = 0 ;
2019-10-13 22:29:09 +01:00
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCommandOpenDevice
2019-10-13 22:29:09 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-13 22:29:09 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCommandOpenDevice > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandOpen
2019-10-13 22:29:09 +01:00
} ,
device_path = devicePath
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-13 22:29:09 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-13 22:29:09 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-13 22:29:09 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2019-10-19 18:28:05 +01:00
lastError = - 1 ;
2020-02-29 18:03:35 +00:00
2019-10-13 22:29:09 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-13 22:29:09 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-13 22:29:09 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-13 22:29:09 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2019-10-19 18:28:05 +01:00
lastError = - 1 ;
2020-02-29 18:03:35 +00:00
2019-10-13 22:29:09 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-13 22:29:09 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-13 22:29:09 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2019-10-19 18:28:05 +01:00
lastError = - 1 ;
2020-02-29 18:03:35 +00:00
2019-10-13 22:29:09 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . Nop )
2019-10-13 22:29:09 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected List Devices Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-19 18:28:05 +01:00
lastError = - 1 ;
2020-02-29 18:03:35 +00:00
2019-10-13 22:29:09 +01:00
return false ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-13 22:29:09 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-13 22:29:09 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2019-10-19 18:28:05 +01:00
lastError = - 1 ;
2020-02-29 18:03:35 +00:00
2019-10-13 22:29:09 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketNop nop = Marshal . ByteArrayToStructureLittleEndian < AaruPacketNop > ( buf ) ;
2019-10-13 22:29:09 +01:00
2020-02-29 18:03:35 +00:00
switch ( nop . reasonCode )
2019-10-13 22:29:09 +01:00
{
2020-02-29 18:03:35 +00:00
case AaruNopReason . OpenOk : return true ;
case AaruNopReason . NotImplemented : throw new NotImplementedException ( $"{nop.reason}" ) ;
2019-10-13 22:29:09 +01:00
}
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( $"{nop.reason}" ) ;
2019-10-19 18:28:05 +01:00
lastError = nop . errno ;
2020-02-29 18:03:35 +00:00
2019-10-13 22:29:09 +01:00
return false ;
}
2019-10-13 23:31:56 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>Sends a SCSI command to the remote device</summary>
/// <returns>0 if no error occurred, otherwise, errno</returns>
/// <param name="cdb">SCSI CDB</param>
/// <param name="buffer">Buffer for SCSI command response</param>
/// <param name="senseBuffer">Buffer with the SCSI sense</param>
/// <param name="timeout">Timeout in seconds</param>
/// <param name="direction">SCSI command transfer direction</param>
/// <param name="duration">Time it took to execute the command in milliseconds</param>
/// <param name="sense">
/// <c>True</c> if SCSI command returned non-OK status and <paramref name="senseBuffer" /> contains
/// SCSI sense
/// </param>
2019-10-13 23:31:56 +01:00
public int SendScsiCommand ( byte [ ] cdb , ref byte [ ] buffer , out byte [ ] senseBuffer , uint timeout ,
2020-02-29 18:03:35 +00:00
ScsiDirection direction , out double duration , out bool sense )
2019-10-13 23:31:56 +01:00
{
2019-10-17 22:15:01 +01:00
senseBuffer = null ;
2020-02-29 18:03:35 +00:00
duration = 0 ;
sense = true ;
2019-10-17 22:15:01 +01:00
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdScsi
2019-10-17 22:15:01 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-17 22:15:01 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandScsi
2019-10-17 22:15:01 +01:00
} ,
2020-07-20 04:34:16 +01:00
direction = ( int ) direction ,
timeout = timeout * 1000
2019-10-17 22:15:01 +01:00
} ;
2020-02-29 18:03:35 +00:00
if ( cdb ! = null )
cmdPkt . cdb_len = ( uint ) cdb . Length ;
if ( buffer ! = null )
cmdPkt . buf_len = ( uint ) buffer . Length ;
2019-10-17 22:15:01 +01:00
2020-02-29 18:03:35 +00:00
cmdPkt . hdr . len = ( uint ) ( Marshal . SizeOf < AaruPacketCmdScsi > ( ) + cmdPkt . cdb_len + cmdPkt . buf_len ) ;
2019-10-17 22:15:01 +01:00
2020-02-29 18:03:35 +00:00
byte [ ] pktBuf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
byte [ ] buf = new byte [ cmdPkt . hdr . len ] ;
2019-10-17 22:15:01 +01:00
2020-02-27 22:42:21 +00:00
Array . Copy ( pktBuf , 0 , buf , 0 , Marshal . SizeOf < AaruPacketCmdScsi > ( ) ) ;
2019-10-17 22:15:01 +01:00
2020-02-29 18:03:35 +00:00
if ( cdb ! = null )
2020-02-27 22:42:21 +00:00
Array . Copy ( cdb , 0 , buf , Marshal . SizeOf < AaruPacketCmdScsi > ( ) , cmdPkt . cdb_len ) ;
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
2020-02-27 22:42:21 +00:00
Array . Copy ( buffer , 0 , buf , Marshal . SizeOf < AaruPacketCmdScsi > ( ) + cmdPkt . cdb_len , cmdPkt . buf_len ) ;
2019-10-17 22:15:01 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-17 22:15:01 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-17 22:15:01 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-17 22:15:01 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-17 22:15:01 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-17 22:15:01 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-17 22:15:01 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-17 22:15:01 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-17 22:15:01 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-17 22:15:01 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-17 22:15:01 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseScsi )
2019-10-17 22:15:01 +01:00
{
2020-02-29 18:03:35 +00:00
AaruConsole . ErrorWriteLine ( "Expected SCSI Response Packet, got packet type {0}..." , hdr . packetType ) ;
2019-10-17 22:15:01 +01:00
return - 1 ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-17 22:15:01 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-17 22:15:01 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-17 22:15:01 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResScsi res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResScsi > ( buf ) ;
2019-10-17 22:15:01 +01:00
senseBuffer = new byte [ res . sense_len ] ;
2020-02-27 22:42:21 +00:00
Array . Copy ( buf , Marshal . SizeOf < AaruPacketResScsi > ( ) , senseBuffer , 0 , res . sense_len ) ;
2019-10-17 22:15:01 +01:00
buffer = new byte [ res . buf_len ] ;
2020-02-27 22:42:21 +00:00
Array . Copy ( buf , Marshal . SizeOf < AaruPacketResScsi > ( ) + res . sense_len , buffer , 0 , res . buf_len ) ;
2019-10-17 22:15:01 +01:00
duration = res . duration ;
2020-02-29 18:03:35 +00:00
sense = res . sense ! = 0 ;
2019-10-17 22:15:01 +01:00
2020-02-29 18:03:35 +00:00
return ( int ) res . error_no ;
2019-10-13 23:31:56 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>Sends an ATA/ATAPI command to the remote device using CHS addressing</summary>
/// <returns>0 if no error occurred, otherwise, errno</returns>
/// <param name="registers">ATA registers.</param>
/// <param name="errorRegisters">Status/error registers.</param>
/// <param name="protocol">ATA Protocol.</param>
/// <param name="transferRegister">Indicates which register indicates the transfer length</param>
/// <param name="buffer">Buffer for ATA/ATAPI command response</param>
/// <param name="timeout">Timeout in seconds</param>
/// <param name="transferBlocks">
/// If set to <c>true</c>, transfer is indicated in blocks, otherwise, it is indicated in
/// bytes.
/// </param>
/// <param name="duration">Time it took to execute the command in milliseconds</param>
/// <param name="sense"><c>True</c> if ATA/ATAPI command returned non-OK status</param>
2019-10-13 23:31:56 +01:00
public int SendAtaCommand ( AtaRegistersChs registers , out AtaErrorRegistersChs errorRegisters ,
2020-02-29 18:03:35 +00:00
AtaProtocol protocol , AtaTransferRegister transferRegister , ref byte [ ] buffer ,
uint timeout , bool transferBlocks , out double duration , out bool sense )
2019-10-13 23:31:56 +01:00
{
2020-02-29 18:03:35 +00:00
duration = 0 ;
sense = true ;
2019-10-19 03:11:27 +01:00
errorRegisters = new AtaErrorRegistersChs ( ) ;
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdAtaChs
2019-10-19 03:11:27 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-19 03:11:27 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandAtaChs
2019-10-19 03:11:27 +01:00
} ,
2020-07-20 04:34:16 +01:00
registers = registers ,
protocol = ( byte ) protocol ,
transferRegister = ( byte ) transferRegister ,
transferBlocks = transferBlocks ,
timeout = timeout * 1000
2019-10-19 03:11:27 +01:00
} ;
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
cmdPkt . buf_len = ( uint ) buffer . Length ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
cmdPkt . hdr . len = ( uint ) ( Marshal . SizeOf < AaruPacketCmdAtaChs > ( ) + cmdPkt . buf_len ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
byte [ ] pktBuf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
byte [ ] buf = new byte [ cmdPkt . hdr . len ] ;
2019-10-19 03:11:27 +01:00
2020-02-27 22:42:21 +00:00
Array . Copy ( pktBuf , 0 , buf , 0 , Marshal . SizeOf < AaruPacketCmdAtaChs > ( ) ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
2020-02-27 22:42:21 +00:00
Array . Copy ( buffer , 0 , buf , Marshal . SizeOf < AaruPacketCmdAtaChs > ( ) , cmdPkt . buf_len ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-19 03:11:27 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-19 03:11:27 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-19 03:11:27 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseAtaChs )
2019-10-19 03:11:27 +01:00
{
2020-02-29 18:03:35 +00:00
AaruConsole . ErrorWriteLine ( "Expected ATA CHS Response Packet, got packet type {0}..." , hdr . packetType ) ;
2019-10-19 03:11:27 +01:00
return - 1 ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResAtaChs res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResAtaChs > ( buf ) ;
2019-10-19 03:11:27 +01:00
buffer = new byte [ res . buf_len ] ;
2020-02-27 22:42:21 +00:00
Array . Copy ( buf , Marshal . SizeOf < AaruPacketResAtaChs > ( ) , buffer , 0 , res . buf_len ) ;
2020-02-29 18:03:35 +00:00
duration = res . duration ;
sense = res . sense ! = 0 ;
2019-10-19 03:11:27 +01:00
errorRegisters = res . registers ;
2020-02-29 18:03:35 +00:00
return ( int ) res . error_no ;
2019-10-13 23:31:56 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>Sends an ATA/ATAPI command to the remote device using 28-bit LBA addressing</summary>
/// <returns>0 if no error occurred, otherwise, errno</returns>
/// <param name="registers">ATA registers.</param>
/// <param name="errorRegisters">Status/error registers.</param>
/// <param name="protocol">ATA Protocol.</param>
/// <param name="transferRegister">Indicates which register indicates the transfer length</param>
/// <param name="buffer">Buffer for ATA/ATAPI command response</param>
/// <param name="timeout">Timeout in seconds</param>
/// <param name="transferBlocks">
/// If set to <c>true</c>, transfer is indicated in blocks, otherwise, it is indicated in
/// bytes.
/// </param>
/// <param name="duration">Time it took to execute the command in milliseconds</param>
/// <param name="sense"><c>True</c> if ATA/ATAPI command returned non-OK status</param>
2019-10-13 23:31:56 +01:00
public int SendAtaCommand ( AtaRegistersLba28 registers , out AtaErrorRegistersLba28 errorRegisters ,
2020-02-29 18:03:35 +00:00
AtaProtocol protocol , AtaTransferRegister transferRegister , ref byte [ ] buffer ,
uint timeout , bool transferBlocks , out double duration , out bool sense )
2019-10-13 23:31:56 +01:00
{
2020-02-29 18:03:35 +00:00
duration = 0 ;
sense = true ;
2019-10-19 03:11:27 +01:00
errorRegisters = new AtaErrorRegistersLba28 ( ) ;
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdAtaLba28
2019-10-19 03:11:27 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-19 03:11:27 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandAtaLba28
2019-10-19 03:11:27 +01:00
} ,
2020-07-20 04:34:16 +01:00
registers = registers ,
protocol = ( byte ) protocol ,
transferRegister = ( byte ) transferRegister ,
transferBlocks = transferBlocks ,
timeout = timeout * 1000
2019-10-19 03:11:27 +01:00
} ;
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
cmdPkt . buf_len = ( uint ) buffer . Length ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
cmdPkt . hdr . len = ( uint ) ( Marshal . SizeOf < AaruPacketCmdAtaLba28 > ( ) + cmdPkt . buf_len ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
byte [ ] pktBuf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
byte [ ] buf = new byte [ cmdPkt . hdr . len ] ;
2019-10-19 03:11:27 +01:00
2020-02-27 22:42:21 +00:00
Array . Copy ( pktBuf , 0 , buf , 0 , Marshal . SizeOf < AaruPacketCmdAtaLba28 > ( ) ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
2020-02-27 22:42:21 +00:00
Array . Copy ( buffer , 0 , buf , Marshal . SizeOf < AaruPacketCmdAtaLba28 > ( ) , cmdPkt . buf_len ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-19 03:11:27 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-19 03:11:27 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-19 03:11:27 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseAtaLba28 )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected ATA LBA28 Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-19 03:11:27 +01:00
return - 1 ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResAtaLba28 res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResAtaLba28 > ( buf ) ;
2019-10-19 03:11:27 +01:00
buffer = new byte [ res . buf_len ] ;
2020-02-27 22:42:21 +00:00
Array . Copy ( buf , Marshal . SizeOf < AaruPacketResAtaLba28 > ( ) , buffer , 0 , res . buf_len ) ;
2020-02-29 18:03:35 +00:00
duration = res . duration ;
sense = res . sense ! = 0 ;
2019-10-19 03:11:27 +01:00
errorRegisters = res . registers ;
2020-02-29 18:03:35 +00:00
return ( int ) res . error_no ;
2019-10-13 23:31:56 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>Sends an ATA/ATAPI command to the remote device using 48-bit LBA addressing</summary>
/// <returns>0 if no error occurred, otherwise, errno</returns>
/// <param name="registers">ATA registers.</param>
/// <param name="errorRegisters">Status/error registers.</param>
/// <param name="protocol">ATA Protocol.</param>
/// <param name="transferRegister">Indicates which register indicates the transfer length</param>
/// <param name="buffer">Buffer for ATA/ATAPI command response</param>
/// <param name="timeout">Timeout in seconds</param>
/// <param name="transferBlocks">
/// If set to <c>true</c>, transfer is indicated in blocks, otherwise, it is indicated in
/// bytes.
/// </param>
/// <param name="duration">Time it took to execute the command in milliseconds</param>
/// <param name="sense"><c>True</c> if ATA/ATAPI command returned non-OK status</param>
2019-10-13 23:31:56 +01:00
public int SendAtaCommand ( AtaRegistersLba48 registers , out AtaErrorRegistersLba48 errorRegisters ,
2020-02-29 18:03:35 +00:00
AtaProtocol protocol , AtaTransferRegister transferRegister , ref byte [ ] buffer ,
uint timeout , bool transferBlocks , out double duration , out bool sense )
2019-10-13 23:31:56 +01:00
{
2020-02-29 18:03:35 +00:00
duration = 0 ;
sense = true ;
2019-10-19 03:11:27 +01:00
errorRegisters = new AtaErrorRegistersLba48 ( ) ;
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdAtaLba48
2019-10-19 03:11:27 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-19 03:11:27 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandAtaLba48
2019-10-19 03:11:27 +01:00
} ,
2020-07-20 04:34:16 +01:00
registers = registers ,
protocol = ( byte ) protocol ,
transferRegister = ( byte ) transferRegister ,
transferBlocks = transferBlocks ,
timeout = timeout * 1000
2019-10-19 03:11:27 +01:00
} ;
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
cmdPkt . buf_len = ( uint ) buffer . Length ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
cmdPkt . hdr . len = ( uint ) ( Marshal . SizeOf < AaruPacketCmdAtaLba48 > ( ) + cmdPkt . buf_len ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
byte [ ] pktBuf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
byte [ ] buf = new byte [ cmdPkt . hdr . len ] ;
2019-10-19 03:11:27 +01:00
2020-02-27 22:42:21 +00:00
Array . Copy ( pktBuf , 0 , buf , 0 , Marshal . SizeOf < AaruPacketCmdAtaLba48 > ( ) ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
2020-02-27 22:42:21 +00:00
Array . Copy ( buffer , 0 , buf , Marshal . SizeOf < AaruPacketCmdAtaLba48 > ( ) , cmdPkt . buf_len ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-19 03:11:27 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-19 03:11:27 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-19 03:11:27 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseAtaLba48 )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected ATA LBA48 Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-19 03:11:27 +01:00
return - 1 ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-19 03:11:27 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-19 03:11:27 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 03:11:27 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResAtaLba48 res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResAtaLba48 > ( buf ) ;
2019-10-19 03:11:27 +01:00
buffer = new byte [ res . buf_len ] ;
2020-02-27 22:42:21 +00:00
Array . Copy ( buf , Marshal . SizeOf < AaruPacketResAtaLba48 > ( ) , buffer , 0 , res . buf_len ) ;
2020-02-29 18:03:35 +00:00
duration = res . duration ;
sense = res . sense ! = 0 ;
2019-10-19 03:11:27 +01:00
errorRegisters = res . registers ;
2020-02-29 18:03:35 +00:00
return ( int ) res . error_no ;
2019-10-13 23:31:56 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>Sends a MMC/SD command to the remote device</summary>
/// <returns>The result of the command.</returns>
/// <param name="command">MMC/SD opcode</param>
/// <param name="buffer">Buffer for MMC/SD command response</param>
/// <param name="timeout">Timeout in seconds</param>
/// <param name="duration">Time it took to execute the command in milliseconds</param>
/// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
/// <param name="write"><c>True</c> if data is sent from host to card</param>
/// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
/// <param name="flags">Flags indicating kind and place of response</param>
/// <param name="blocks">How many blocks to transfer</param>
/// <param name="argument">Command argument</param>
/// <param name="response">Response registers</param>
/// <param name="blockSize">Size of block in bytes</param>
2020-02-29 18:03:35 +00:00
public int SendMmcCommand ( MmcCommands command , bool write , bool isApplication , MmcFlags flags , uint argument ,
uint blockSize , uint blocks , ref byte [ ] buffer , out uint [ ] response ,
out double duration , out bool sense , uint timeout = 0 )
2019-10-13 23:31:56 +01:00
{
2019-10-19 17:43:46 +01:00
duration = 0 ;
2020-02-29 18:03:35 +00:00
sense = true ;
2019-10-19 17:43:46 +01:00
response = null ;
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdSdhci
2019-10-19 17:43:46 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-19 17:43:46 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
version = Consts . PACKET_VERSION ,
2020-12-13 22:04:33 +00:00
packetType = AaruPacketType . CommandSdhci
2019-10-19 17:43:46 +01:00
} ,
2020-12-13 22:04:33 +00:00
command = new AaruCmdSdhci
{
command = command ,
write = write ,
application = isApplication ,
flags = flags ,
argument = argument ,
block_size = blockSize ,
blocks = blocks ,
timeout = timeout * 1000
}
2019-10-19 17:43:46 +01:00
} ;
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
2020-12-13 22:04:33 +00:00
cmdPkt . command . buf_len = ( uint ) buffer . Length ;
2019-10-19 17:43:46 +01:00
2020-12-13 22:04:33 +00:00
cmdPkt . hdr . len = ( uint ) ( Marshal . SizeOf < AaruPacketCmdSdhci > ( ) + cmdPkt . command . buf_len ) ;
2019-10-19 17:43:46 +01:00
2020-02-29 18:03:35 +00:00
byte [ ] pktBuf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
byte [ ] buf = new byte [ cmdPkt . hdr . len ] ;
2019-10-19 17:43:46 +01:00
2020-02-27 22:42:21 +00:00
Array . Copy ( pktBuf , 0 , buf , 0 , Marshal . SizeOf < AaruPacketCmdSdhci > ( ) ) ;
2019-10-19 17:43:46 +01:00
2020-02-29 18:03:35 +00:00
if ( buffer ! = null )
2020-12-13 22:04:33 +00:00
Array . Copy ( buffer , 0 , buf , Marshal . SizeOf < AaruPacketCmdSdhci > ( ) , cmdPkt . command . buf_len ) ;
2019-10-19 17:43:46 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-19 17:43:46 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-19 17:43:46 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 17:43:46 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-19 17:43:46 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-19 17:43:46 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-19 17:43:46 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 17:43:46 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-19 17:43:46 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-19 17:43:46 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 17:43:46 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseSdhci )
2019-10-19 17:43:46 +01:00
{
2020-02-29 18:03:35 +00:00
AaruConsole . ErrorWriteLine ( "Expected SDHCI Response Packet, got packet type {0}..." , hdr . packetType ) ;
2019-10-19 17:43:46 +01:00
return - 1 ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-19 17:43:46 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-19 17:43:46 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 17:43:46 +01:00
return - 1 ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResSdhci res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResSdhci > ( buf ) ;
2019-10-19 17:43:46 +01:00
2020-12-13 22:04:33 +00:00
buffer = new byte [ res . res . buf_len ] ;
Array . Copy ( buf , Marshal . SizeOf < AaruPacketResSdhci > ( ) , buffer , 0 , res . res . buf_len ) ;
duration = res . res . duration ;
sense = res . res . sense ! = 0 ;
2020-02-29 18:03:35 +00:00
response = new uint [ 4 ] ;
2020-12-13 22:04:33 +00:00
response [ 0 ] = res . res . response [ 0 ] ;
response [ 1 ] = res . res . response [ 1 ] ;
response [ 2 ] = res . res . response [ 2 ] ;
response [ 3 ] = res . res . response [ 3 ] ;
2019-10-19 17:43:46 +01:00
2020-12-13 22:04:33 +00:00
return ( int ) res . res . error_no ;
2019-10-13 23:31:56 +01:00
}
2019-10-14 01:02:25 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Gets the <see cref="DeviceType"/> for the remote device
/// </summary>
/// <returns><see cref="DeviceType"/></returns>
2019-10-14 01:02:25 +01:00
public DeviceType GetDeviceType ( )
{
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdGetDeviceType
2019-10-16 20:07:24 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-16 20:07:24 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCmdGetDeviceType > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandGetType
2019-10-16 20:07:24 +01:00
}
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-16 20:07:24 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-16 20:07:24 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-16 20:07:24 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-16 20:07:24 +01:00
return DeviceType . Unknown ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-16 20:07:24 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-16 20:07:24 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-16 20:07:24 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-16 20:07:24 +01:00
return DeviceType . Unknown ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-16 20:07:24 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-16 20:07:24 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-16 20:07:24 +01:00
return DeviceType . Unknown ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseGetType )
2019-10-16 20:07:24 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected Device Type Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-16 20:07:24 +01:00
return DeviceType . Unknown ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-16 20:07:24 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-16 20:07:24 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-16 20:07:24 +01:00
return DeviceType . Unknown ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResGetDeviceType res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResGetDeviceType > ( buf ) ;
2019-10-16 20:07:24 +01:00
return res . device_type ;
2019-10-14 01:02:25 +01:00
}
2019-10-14 01:11:20 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Retrieves the SDHCI registers from the remote device
/// </summary>
/// <param name="csd">CSD register</param>
/// <param name="cid">CID register</param>
/// <param name="ocr">OCR register</param>
/// <param name="scr">SCR register</param>
/// <returns><c>true</c> if the device is attached to an SDHCI controller, <c>false</c> otherwise</returns>
2019-10-14 01:11:20 +01:00
public bool GetSdhciRegisters ( out byte [ ] csd , out byte [ ] cid , out byte [ ] ocr , out byte [ ] scr )
{
2019-10-18 00:27:53 +01:00
csd = null ;
cid = null ;
ocr = null ;
scr = null ;
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdGetSdhciRegisters
2019-10-18 00:27:53 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-18 00:27:53 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCmdGetSdhciRegisters > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandGetSdhciRegisters
2019-10-18 00:27:53 +01:00
}
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-18 00:27:53 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-18 00:27:53 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-18 00:27:53 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-18 00:27:53 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-18 00:27:53 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-18 00:27:53 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-18 00:27:53 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-18 00:27:53 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-18 00:27:53 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-18 00:27:53 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-18 00:27:53 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseGetSdhciRegisters )
2019-10-18 00:27:53 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected Device Type Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-18 00:27:53 +01:00
return false ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-18 00:27:53 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-18 00:27:53 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-18 00:27:53 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResGetSdhciRegisters res =
Marshal . ByteArrayToStructureLittleEndian < AaruPacketResGetSdhciRegisters > ( buf ) ;
2019-10-18 00:27:53 +01:00
2020-02-29 18:03:35 +00:00
if ( res . csd_len > 0 )
2019-10-18 00:27:53 +01:00
{
2020-02-29 18:03:35 +00:00
if ( res . csd_len > 16 )
2019-10-18 00:27:53 +01:00
res . csd_len = 16 ;
csd = new byte [ res . csd_len ] ;
Array . Copy ( res . csd , 0 , csd , 0 , res . csd_len ) ;
}
2020-02-29 18:03:35 +00:00
if ( res . cid_len > 0 )
2019-10-18 00:27:53 +01:00
{
2020-02-29 18:03:35 +00:00
if ( res . cid_len > 16 )
2019-10-18 00:27:53 +01:00
res . cid_len = 16 ;
cid = new byte [ res . cid_len ] ;
Array . Copy ( res . cid , 0 , cid , 0 , res . cid_len ) ;
}
2020-02-29 18:03:35 +00:00
if ( res . ocr_len > 0 )
2019-10-18 00:27:53 +01:00
{
2020-02-29 18:03:35 +00:00
if ( res . ocr_len > 16 )
2019-10-18 00:27:53 +01:00
res . ocr_len = 16 ;
ocr = new byte [ res . ocr_len ] ;
Array . Copy ( res . ocr , 0 , ocr , 0 , res . ocr_len ) ;
}
2020-02-29 18:03:35 +00:00
if ( res . scr_len > 0 )
2019-10-18 00:27:53 +01:00
{
2020-02-29 18:03:35 +00:00
if ( res . scr_len > 16 )
2019-10-18 00:27:53 +01:00
res . scr_len = 16 ;
scr = new byte [ res . scr_len ] ;
Array . Copy ( res . scr , 0 , scr , 0 , res . scr_len ) ;
}
return res . isSdhci ;
2019-10-14 01:11:20 +01:00
}
2019-10-14 01:27:05 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Gets the USB data from the remote device
/// </summary>
/// <param name="descriptors">USB descriptors</param>
/// <param name="idVendor">USB vendor ID</param>
/// <param name="idProduct">USB product ID</param>
/// <param name="manufacturer">USB manufacturer string</param>
/// <param name="product">USB product string</param>
/// <param name="serial">USB serial number string</param>
/// <returns><c>true</c> if the device is attached via USB, <c>false</c> otherwise</returns>
2019-10-14 01:27:05 +01:00
public bool GetUsbData ( out byte [ ] descriptors , out ushort idVendor , out ushort idProduct ,
2020-02-29 18:03:35 +00:00
out string manufacturer , out string product , out string serial )
2019-10-14 01:27:05 +01:00
{
2020-02-29 18:03:35 +00:00
descriptors = null ;
idVendor = 0 ;
idProduct = 0 ;
2019-10-18 23:42:18 +01:00
manufacturer = null ;
2020-02-29 18:03:35 +00:00
product = null ;
serial = null ;
2019-10-18 23:42:18 +01:00
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdGetUsbData
2019-10-18 23:42:18 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-18 23:42:18 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCmdGetUsbData > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandGetUsbData
2019-10-18 23:42:18 +01:00
}
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-18 23:42:18 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-18 23:42:18 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-18 23:42:18 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-18 23:42:18 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-18 23:42:18 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-18 23:42:18 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-18 23:42:18 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-18 23:42:18 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-18 23:42:18 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-18 23:42:18 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-18 23:42:18 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseGetUsbData )
2019-10-18 23:42:18 +01:00
{
2020-02-29 18:03:35 +00:00
AaruConsole . ErrorWriteLine ( "Expected USB Data Response Packet, got packet type {0}..." , hdr . packetType ) ;
2019-10-18 23:42:18 +01:00
return false ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-18 23:42:18 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-18 23:42:18 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-18 23:42:18 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResGetUsbData res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResGetUsbData > ( buf ) ;
2019-10-18 23:42:18 +01:00
2020-02-29 18:03:35 +00:00
if ( ! res . isUsb )
2019-10-18 23:42:18 +01:00
return false ;
descriptors = new byte [ res . descLen ] ;
Array . Copy ( res . descriptors , 0 , descriptors , 0 , res . descLen ) ;
2020-02-29 18:03:35 +00:00
idVendor = res . idVendor ;
idProduct = res . idProduct ;
2019-10-18 23:42:18 +01:00
manufacturer = res . manufacturer ;
2020-02-29 18:03:35 +00:00
product = res . product ;
serial = res . serial ;
2019-10-18 23:42:18 +01:00
return true ;
2019-10-14 01:27:05 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Gets the FireWire data from the remote device
/// </summary>
/// <param name="idVendor">FireWire vendor ID</param>
/// <param name="idProduct">FireWire product ID</param>
/// <param name="vendor">FireWire vendor string</param>
/// <param name="model">FireWire model string</param>
/// <param name="guid">FireWire GUID</param>
/// <returns><c>true</c> if the device is attached via FireWire, <c>false</c> otherwise</returns>
2020-02-29 18:03:35 +00:00
public bool GetFireWireData ( out uint idVendor , out uint idProduct , out ulong guid , out string vendor ,
out string model )
2019-10-14 01:27:05 +01:00
{
2020-02-29 18:03:35 +00:00
idVendor = 0 ;
2019-10-19 00:08:33 +01:00
idProduct = 0 ;
2020-02-29 18:03:35 +00:00
guid = 0 ;
vendor = null ;
model = null ;
2019-10-19 00:08:33 +01:00
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdGetFireWireData
2019-10-19 00:08:33 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-19 00:08:33 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCmdGetFireWireData > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandGetFireWireData
2019-10-19 00:08:33 +01:00
}
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-19 00:08:33 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-19 00:08:33 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-19 00:08:33 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 00:08:33 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-19 00:08:33 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-19 00:08:33 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-19 00:08:33 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 00:08:33 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-19 00:08:33 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-19 00:08:33 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 00:08:33 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseGetFireWireData )
2019-10-19 00:08:33 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected FireWire Data Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-19 00:08:33 +01:00
return false ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-19 00:08:33 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-19 00:08:33 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 00:08:33 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResGetFireWireData res =
Marshal . ByteArrayToStructureLittleEndian < AaruPacketResGetFireWireData > ( buf ) ;
2019-10-19 00:08:33 +01:00
2020-02-29 18:03:35 +00:00
if ( ! res . isFireWire )
2019-10-19 00:08:33 +01:00
return false ;
2020-02-29 18:03:35 +00:00
idVendor = res . idVendor ;
2019-10-19 00:08:33 +01:00
idProduct = res . idModel ;
2020-02-29 18:03:35 +00:00
guid = res . guid ;
vendor = res . vendor ;
model = res . model ;
2019-10-19 00:08:33 +01:00
return true ;
2019-10-14 01:27:05 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Gets the PCMCIA/CardBus data from the remote device
/// </summary>
/// <param name="cis">Card Information Structure</param>
/// <returns><c>true</c> if the device is attached via PCMCIA or CardBus, <c>false</c> otherwise</returns>
2019-10-14 01:27:05 +01:00
public bool GetPcmciaData ( out byte [ ] cis )
{
2019-10-19 01:10:06 +01:00
cis = null ;
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdGetPcmciaData
2019-10-19 01:10:06 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-19 01:10:06 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCmdGetPcmciaData > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandGetPcmciaData
2019-10-19 01:10:06 +01:00
}
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-19 01:10:06 +01:00
2020-02-29 18:03:35 +00:00
int len = _socket . Send ( buf , SocketFlags . None ) ;
2019-10-19 01:10:06 +01:00
2020-02-29 18:03:35 +00:00
if ( len ! = buf . Length )
2019-10-19 01:10:06 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 01:10:06 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
2019-10-19 01:10:06 +01:00
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
2019-10-19 01:10:06 +01:00
2020-02-29 18:03:35 +00:00
if ( len < hdrBuf . Length )
2019-10-19 01:10:06 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 01:10:06 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
2019-10-19 01:10:06 +01:00
2020-07-20 21:11:32 +01:00
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
2019-10-19 01:10:06 +01:00
{
2020-02-28 00:19:50 +00:00
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 01:10:06 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
if ( hdr . packetType ! = AaruPacketType . ResponseGetPcmciaData )
2019-10-19 01:10:06 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Expected PCMCIA Data Response Packet, got packet type {0}..." ,
2020-02-29 18:03:35 +00:00
hdr . packetType ) ;
2019-10-19 01:10:06 +01:00
return false ;
}
buf = new byte [ hdr . len ] ;
2019-10-21 19:05:19 +01:00
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
2019-10-19 01:10:06 +01:00
2020-02-29 18:03:35 +00:00
if ( len < buf . Length )
2019-10-19 01:10:06 +01:00
{
2020-02-27 23:48:41 +00:00
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
2020-02-29 18:03:35 +00:00
2019-10-19 01:10:06 +01:00
return false ;
}
2020-02-29 18:03:35 +00:00
AaruPacketResGetPcmciaData res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResGetPcmciaData > ( buf ) ;
2019-10-19 01:10:06 +01:00
2020-02-29 18:03:35 +00:00
if ( ! res . isPcmcia )
2019-10-19 01:10:06 +01:00
return false ;
cis = res . cis ;
return true ;
2019-10-14 01:27:05 +01:00
}
2019-10-21 19:05:19 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Receives data from a socket into a buffer
/// </summary>
/// <param name="socket">Socket</param>
/// <param name="buffer">Data buffer</param>
/// <param name="size">Expected total size in bytes</param>
/// <param name="socketFlags">Socket flags</param>
/// <returns>Retrieved number of bytes</returns>
2020-02-29 18:03:35 +00:00
static int Receive ( Socket socket , byte [ ] buffer , int size , SocketFlags socketFlags )
2019-10-21 19:05:19 +01:00
{
2020-02-29 18:03:35 +00:00
int offset = 0 ;
2019-10-21 19:05:19 +01:00
2020-02-29 18:03:35 +00:00
while ( size > 0 )
2019-10-21 19:05:19 +01:00
{
2020-11-11 04:19:18 +00:00
int got = socket . Receive ( buffer , offset , size , socketFlags ) ;
2019-10-21 19:05:19 +01:00
2020-11-11 04:19:18 +00:00
if ( got < = 0 )
2020-02-29 18:03:35 +00:00
break ;
2019-10-21 19:05:19 +01:00
2020-11-11 04:19:18 +00:00
offset + = got ;
size - = got ;
2019-10-21 19:05:19 +01:00
}
return offset ;
}
2019-10-26 15:47:36 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Closes the remote device, without closing the network connection
/// </summary>
2019-10-26 15:47:36 +01:00
public void Close ( )
{
2020-02-27 22:42:21 +00:00
var cmdPkt = new AaruPacketCmdClose
2019-10-26 15:47:36 +01:00
{
2020-02-27 22:42:21 +00:00
hdr = new AaruPacketHeader
2019-10-26 15:47:36 +01:00
{
2020-07-20 21:11:32 +01:00
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
2020-07-20 04:34:16 +01:00
len = ( uint ) Marshal . SizeOf < AaruPacketCmdClose > ( ) ,
2020-07-20 21:11:32 +01:00
version = Consts . PACKET_VERSION ,
2020-02-27 22:42:21 +00:00
packetType = AaruPacketType . CommandCloseDevice
2019-10-26 15:47:36 +01:00
}
} ;
2020-02-29 18:03:35 +00:00
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
2019-10-26 15:47:36 +01:00
2020-10-17 00:19:31 +01:00
try
{
_socket . Send ( buf , SocketFlags . None ) ;
}
catch ( ObjectDisposedException )
{
// Ignore if already disposed
}
2019-10-26 15:47:36 +01:00
}
2020-12-12 20:58:58 +00:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Concatenates a queue of commands to be send to a remote SecureDigital or MultiMediaCard attached to an SDHCI controller
/// </summary>
/// <param name="commands">List of commands</param>
/// <param name="duration">Duration to execute all commands, in milliseconds</param>
/// <param name="sense">Set to <c>true</c> if any of the commands returned an error status, <c>false</c> otherwise</param>
/// <param name="timeout">Maximum allowed time to execute a single command</param>
/// <returns>0 if no error occurred, otherwise, errno</returns>
2020-12-12 20:58:58 +00:00
public int SendMultipleMmcCommands ( Device . MmcSingleCommand [ ] commands , out double duration , out bool sense ,
uint timeout = 0 )
{
2020-12-13 20:45:22 +00:00
if ( ServerProtocolVersion < 2 )
return SendMultipleMmcCommandsV1 ( commands , out duration , out sense , timeout ) ;
2020-12-13 22:04:33 +00:00
sense = false ;
duration = 0 ;
long packetSize = Marshal . SizeOf < AaruPacketMultiCmdSdhci > ( ) +
( Marshal . SizeOf < AaruCmdSdhci > ( ) * commands . LongLength ) ;
foreach ( Device . MmcSingleCommand command in commands )
packetSize + = command . buffer ? . Length ? ? 0 ;
var packet = new AaruPacketMultiCmdSdhci
{
cmd_count = ( ulong ) commands . LongLength ,
hdr = new AaruPacketHeader
{
len = ( uint ) packetSize ,
packetType = AaruPacketType . MultiCommandSdhci ,
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
version = Consts . PACKET_VERSION
}
} ;
byte [ ] buf = new byte [ packetSize ] ;
byte [ ] tmp = Marshal . StructureToByteArrayLittleEndian ( packet ) ;
Array . Copy ( tmp , 0 , buf , 0 , tmp . Length ) ;
int off = tmp . Length ;
foreach ( Device . MmcSingleCommand command in commands )
{
var cmd = new AaruCmdSdhci
{
application = command . isApplication ,
argument = command . argument ,
block_size = command . blockSize ,
blocks = command . blocks ,
buf_len = ( uint ) ( command . buffer ? . Length ? ? 0 ) ,
command = command . command ,
flags = command . flags ,
timeout = timeout ,
write = command . write
} ;
tmp = Marshal . StructureToByteArrayLittleEndian ( cmd ) ;
Array . Copy ( tmp , 0 , buf , off , tmp . Length ) ;
off + = tmp . Length ;
}
foreach ( Device . MmcSingleCommand command in commands )
{
if ( ( command . buffer ? . Length ? ? 0 ) = = 0 )
continue ;
Array . Copy ( command . buffer , 0 , buf , off , command . buffer . Length ) ;
off + = command . buffer . Length ;
}
int len = _socket . Send ( buf , SocketFlags . None ) ;
if ( len ! = buf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
return - 1 ;
}
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
if ( len < hdrBuf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
return - 1 ;
}
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
{
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
return - 1 ;
}
if ( hdr . packetType ! = AaruPacketType . ResponseMultiSdhci )
{
AaruConsole . ErrorWriteLine ( "Expected multi MMC/SD command Response Packet, got packet type {0}..." ,
hdr . packetType ) ;
return - 1 ;
}
buf = new byte [ hdr . len ] ;
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
if ( len < buf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
return - 1 ;
}
AaruPacketMultiCmdSdhci res = Marshal . ByteArrayToStructureLittleEndian < AaruPacketMultiCmdSdhci > ( buf ) ;
if ( res . cmd_count ! = ( ulong ) commands . Length )
{
AaruConsole . ErrorWriteLine ( "Expected the response to {0} SD/MMC commands, but got {1} responses..." ,
commands . Length , res . cmd_count ) ;
return - 1 ;
}
off = Marshal . SizeOf < AaruPacketMultiCmdSdhci > ( ) ;
int error = 0 ;
foreach ( Device . MmcSingleCommand command in commands )
{
AaruResSdhci cmdRes =
Marshal . ByteArrayToStructureLittleEndian < AaruResSdhci > ( buf , off , Marshal . SizeOf < AaruResSdhci > ( ) ) ;
command . response = cmdRes . response ;
duration + = cmdRes . duration ;
if ( cmdRes . error_no ! = 0 & &
error = = 0 )
error = ( int ) cmdRes . error_no ;
if ( cmdRes . sense ! = 0 )
sense = true ;
if ( cmdRes . buf_len > 0 )
command . buffer = new byte [ cmdRes . buf_len ] ;
off + = Marshal . SizeOf < AaruResSdhci > ( ) ;
}
foreach ( Device . MmcSingleCommand command in commands )
{
Array . Copy ( buf , off , command . buffer , 0 , command . buffer . Length ) ;
off + = command . buffer . Length ;
}
return error ;
2020-12-13 20:45:22 +00:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Concatenates a queue of commands to be send to a remote SecureDigital or MultiMediaCard attached to an SDHCI controller, using protocol version 1 without specific support for such a queueing
/// </summary>
/// <param name="commands">List of commands</param>
/// <param name="duration">Duration to execute all commands, in milliseconds</param>
/// <param name="sense">Set to <c>true</c> if any of the commands returned an error status, <c>false</c> otherwise</param>
/// <param name="timeout">Maximum allowed time to execute a single command</param>
/// <returns>0 if no error occurred, otherwise, errno</returns>
2020-12-13 20:45:22 +00:00
int SendMultipleMmcCommandsV1 ( Device . MmcSingleCommand [ ] commands , out double duration , out bool sense ,
2020-12-13 22:04:33 +00:00
uint timeout )
2020-12-13 20:45:22 +00:00
{
sense = false ;
2020-12-12 20:58:58 +00:00
duration = 0 ;
2020-12-13 20:45:22 +00:00
int error = 0 ;
foreach ( Device . MmcSingleCommand command in commands )
{
error = 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 ( cmdSense )
sense = true ;
duration + = cmdDuration ;
}
2020-12-12 20:58:58 +00:00
2020-12-13 20:45:22 +00:00
return error ;
2020-12-12 20:58:58 +00:00
}
2020-12-12 21:03:01 +00:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Closes then immediately reopens a remote device
/// </summary>
/// <returns>Returned error number if any</returns>
2020-12-13 22:16:03 +00:00
public bool ReOpen ( )
{
2020-12-13 23:32:39 +00:00
if ( ServerProtocolVersion < 2 )
return false ;
2020-12-13 22:16:03 +00:00
var cmdPkt = new AaruPacketCmdReOpen
{
hdr = new AaruPacketHeader
{
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
len = ( uint ) Marshal . SizeOf < AaruPacketCmdReOpen > ( ) ,
version = Consts . PACKET_VERSION ,
packetType = AaruPacketType . CommandReOpenDevice
}
} ;
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
int len = _socket . Send ( buf , SocketFlags . None ) ;
if ( len ! = buf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
return false ;
}
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
if ( len < hdrBuf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
return false ;
}
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
{
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
return false ;
}
if ( hdr . packetType ! = AaruPacketType . Nop )
{
2020-12-13 23:30:21 +00:00
AaruConsole . ErrorWriteLine ( "Expected NOP Packet, got packet type {0}..." , hdr . packetType ) ;
2020-12-13 22:16:03 +00:00
return false ;
}
if ( hdr . version ! = Consts . PACKET_VERSION )
{
AaruConsole . ErrorWriteLine ( "Unrecognized packet version..." ) ;
return false ;
}
buf = new byte [ hdr . len ] ;
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
if ( len < buf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
return false ;
}
AaruPacketNop nop = Marshal . ByteArrayToStructureLittleEndian < AaruPacketNop > ( buf ) ;
switch ( nop . reasonCode )
{
case AaruNopReason . ReOpenOk : return true ;
case AaruNopReason . CloseError :
case AaruNopReason . OpenError :
AaruConsole . ErrorWriteLine ( "ReOpen error closing device..." ) ;
break ;
default :
AaruConsole . ErrorWriteLine ( "ReOpen error {0} with reason: {1}..." , nop . errno , nop . reason ) ;
break ;
}
return false ;
}
2020-12-12 22:48:03 +00:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Reads data using operating system buffers.
/// </summary>
/// <param name="buffer">Data buffer</param>
/// <param name="offset">Offset in remote device to start reading, in bytes</param>
/// <param name="length">Number of bytes to read</param>
/// <param name="duration">Total time in milliseconds the reading took</param>
/// <returns><c>true</c> if there was an error, <c>false</c> otherwise</returns>
2020-12-13 23:30:21 +00:00
public bool BufferedOsRead ( out byte [ ] buffer , long offset , uint length , out double duration )
{
duration = 0 ;
buffer = null ;
2020-12-13 23:32:39 +00:00
if ( ServerProtocolVersion < 2 )
return false ;
2020-12-13 23:30:21 +00:00
var cmdPkt = new AaruPacketCmdOsRead
{
hdr = new AaruPacketHeader
{
remote_id = Consts . REMOTE_ID ,
packet_id = Consts . PACKET_ID ,
len = ( uint ) Marshal . SizeOf < AaruPacketCmdOsRead > ( ) ,
version = Consts . PACKET_VERSION ,
packetType = AaruPacketType . CommandOsRead
} ,
length = length ,
offset = ( ulong ) offset
} ;
byte [ ] buf = Marshal . StructureToByteArrayLittleEndian ( cmdPkt ) ;
int len = _socket . Send ( buf , SocketFlags . None ) ;
if ( len ! = buf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not write to the network..." ) ;
return false ;
}
byte [ ] hdrBuf = new byte [ Marshal . SizeOf < AaruPacketHeader > ( ) ] ;
len = Receive ( _socket , hdrBuf , hdrBuf . Length , SocketFlags . Peek ) ;
if ( len < hdrBuf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
return false ;
}
AaruPacketHeader hdr = Marshal . ByteArrayToStructureLittleEndian < AaruPacketHeader > ( hdrBuf ) ;
if ( hdr . remote_id ! = Consts . REMOTE_ID | |
hdr . packet_id ! = Consts . PACKET_ID )
{
AaruConsole . ErrorWriteLine ( "Received data is not an Aaru Remote Packet..." ) ;
return false ;
}
if ( hdr . packetType ! = AaruPacketType . ResponseOsRead )
{
AaruConsole . ErrorWriteLine ( "Expected OS Read Response Packet, got packet type {0}..." , hdr . packetType ) ;
return false ;
}
if ( hdr . version ! = Consts . PACKET_VERSION )
{
AaruConsole . ErrorWriteLine ( "Unrecognized packet version..." ) ;
return false ;
}
buf = new byte [ hdr . len ] ;
len = Receive ( _socket , buf , buf . Length , SocketFlags . None ) ;
if ( len < buf . Length )
{
AaruConsole . ErrorWriteLine ( "Could not read from the network..." ) ;
return false ;
}
AaruPacketResOsRead osRead = Marshal . ByteArrayToStructureLittleEndian < AaruPacketResOsRead > ( buf ) ;
duration = osRead . duration ;
if ( osRead . errno ! = 0 )
{
AaruConsole . ErrorWriteLine ( "Remote error {0} in OS Read..." , osRead . errno ) ;
return false ;
}
buffer = new byte [ length ] ;
Array . Copy ( buf , Marshal . SizeOf < AaruPacketResOsRead > ( ) , buffer , 0 , length ) ;
return true ;
}
2019-10-12 22:51:50 +01:00
}
}