diff --git a/DiscImageChef.Devices/Device/Constructor.cs b/DiscImageChef.Devices/Device/Constructor.cs index 5ee6e8439..c2629307e 100644 --- a/DiscImageChef.Devices/Device/Constructor.cs +++ b/DiscImageChef.Devices/Device/Constructor.cs @@ -76,75 +76,78 @@ namespace DiscImageChef.Devices remote = new Remote.Remote(host); - throw new NotImplementedException("Remote devices not yet implemented..."); + Error = remote.Open(devicePath, out var errno); + LastError = errno; } - - switch (PlatformId) + else { - case PlatformID.Win32NT: + switch (PlatformId) { - FileHandle = Extern.CreateFile(devicePath, FileAccess.GenericRead | FileAccess.GenericWrite, - FileShare.Read | FileShare.Write, IntPtr.Zero, - FileMode.OpenExisting, - FileAttributes.Normal, IntPtr.Zero); - - if (((SafeFileHandle) FileHandle).IsInvalid) + case PlatformID.Win32NT: { - Error = true; - LastError = Marshal.GetLastWin32Error(); - } + FileHandle = Extern.CreateFile(devicePath, FileAccess.GenericRead | FileAccess.GenericWrite, + FileShare.Read | FileShare.Write, IntPtr.Zero, + FileMode.OpenExisting, + FileAttributes.Normal, IntPtr.Zero); - break; - } - case PlatformID.Linux: - { - FileHandle = - Linux.Extern.open(devicePath, - FileFlags.ReadWrite | FileFlags.NonBlocking | FileFlags.CreateNew); - - if ((int) FileHandle < 0) - { - LastError = Marshal.GetLastWin32Error(); - - if (LastError == 13 || LastError == 30) // EACCES or EROFS - { - FileHandle = Linux.Extern.open(devicePath, FileFlags.Readonly | FileFlags.NonBlocking); - if ((int) FileHandle < 0) - { - Error = true; - LastError = Marshal.GetLastWin32Error(); - } - } - else + if (((SafeFileHandle) FileHandle).IsInvalid) { Error = true; + LastError = Marshal.GetLastWin32Error(); } - LastError = Marshal.GetLastWin32Error(); + break; } - - break; - } - case PlatformID.FreeBSD: - { - FileHandle = FreeBSD.Extern.cam_open_device(devicePath, FreeBSD.FileFlags.ReadWrite); - - if (((IntPtr) FileHandle).ToInt64() == 0) + case PlatformID.Linux: { - Error = true; - LastError = Marshal.GetLastWin32Error(); + FileHandle = + Linux.Extern.open(devicePath, + FileFlags.ReadWrite | FileFlags.NonBlocking | FileFlags.CreateNew); + + if ((int) FileHandle < 0) + { + LastError = Marshal.GetLastWin32Error(); + + if (LastError == 13 || LastError == 30) // EACCES or EROFS + { + FileHandle = Linux.Extern.open(devicePath, FileFlags.Readonly | FileFlags.NonBlocking); + if ((int) FileHandle < 0) + { + Error = true; + LastError = Marshal.GetLastWin32Error(); + } + } + else + { + Error = true; + } + + LastError = Marshal.GetLastWin32Error(); + } + + break; } + case PlatformID.FreeBSD: + { + FileHandle = FreeBSD.Extern.cam_open_device(devicePath, FreeBSD.FileFlags.ReadWrite); - var camDevice = (CamDevice) Marshal.PtrToStructure((IntPtr) FileHandle, typeof(CamDevice)); + if (((IntPtr) FileHandle).ToInt64() == 0) + { + Error = true; + LastError = Marshal.GetLastWin32Error(); + } - if (StringHandlers.CToString(camDevice.SimName) == "ata") - throw new - InvalidOperationException( - "Parallel ATA devices are not supported on FreeBSD due to upstream bug #224250."); + var camDevice = (CamDevice) Marshal.PtrToStructure((IntPtr) FileHandle, typeof(CamDevice)); - break; + if (StringHandlers.CToString(camDevice.SimName) == "ata") + throw new + InvalidOperationException( + "Parallel ATA devices are not supported on FreeBSD due to upstream bug #224250."); + + break; + } + default: throw new InvalidOperationException($"Platform {PlatformId} not yet supported."); } - default: throw new InvalidOperationException($"Platform {PlatformId} not yet supported."); } if (Error) throw new SystemException($"Error {LastError} opening device."); diff --git a/DiscImageChef.Devices/Remote/Enums.cs b/DiscImageChef.Devices/Remote/Enums.cs index aa225a1aa..a15042994 100644 --- a/DiscImageChef.Devices/Remote/Enums.cs +++ b/DiscImageChef.Devices/Remote/Enums.cs @@ -8,4 +8,14 @@ namespace DiscImageChef.Devices.Remote ResponseListDevices = 3, CommandOpen = 4 } + + public enum DicNopReason : byte + { + OutOfOrder = 0, + NotImplemented = 1, + NotRecognized = 2, + ErrorListDevices = 3, + OpenOk = 4, + OpenError = 5 + } } \ No newline at end of file diff --git a/DiscImageChef.Devices/Remote/Remote.cs b/DiscImageChef.Devices/Remote/Remote.cs index 65d3f155a..c472ba39a 100644 --- a/DiscImageChef.Devices/Remote/Remote.cs +++ b/DiscImageChef.Devices/Remote/Remote.cs @@ -245,5 +245,85 @@ namespace DiscImageChef.Devices.Remote return devices.ToArray(); } + + public bool Open(string devicePath, out int LastError) + { + LastError = 0; + + var cmdPkt = new DicPacketCommandOpenDevice + { + hdr = new DicPacketHeader + { + id = Consts.PacketId, + len = (uint) Marshal.SizeOf(), + version = Consts.PacketVersion, + packetType = DicPacketType.CommandOpen + }, + device_path = devicePath + }; + + var buf = Marshal.StructureToByteArrayLittleEndian(cmdPkt); + + var len = _socket.Send(buf, SocketFlags.None); + + if (len != buf.Length) + { + DicConsole.ErrorWriteLine("Could not write to the network..."); + LastError = -1; + return false; + } + + var hdrBuf = new byte[Marshal.SizeOf()]; + + len = _socket.Receive(hdrBuf, hdrBuf.Length, SocketFlags.Peek); + + if (len < hdrBuf.Length) + { + DicConsole.ErrorWriteLine("Could not read from the network..."); + LastError = -1; + return false; + } + + var hdr = Marshal.ByteArrayToStructureLittleEndian(hdrBuf); + + if (hdr.id != Consts.PacketId) + { + DicConsole.ErrorWriteLine("Received data is not a DIC Remote Packet..."); + LastError = -1; + return false; + } + + if (hdr.packetType != DicPacketType.Nop) + { + DicConsole.ErrorWriteLine("Expected List Devices Response Packet, got packet type {0}...", + hdr.packetType); + LastError = -1; + return false; + } + + buf = new byte[hdr.len]; + len = _socket.Receive(buf, buf.Length, SocketFlags.None); + + if (len < buf.Length) + { + DicConsole.ErrorWriteLine("Could not read from the network..."); + LastError = -1; + return false; + } + + var nop = Marshal.ByteArrayToStructureLittleEndian(buf); + + switch (nop.reasonCode) + { + case DicNopReason.OpenOk: + return true; + case DicNopReason.NotImplemented: + throw new NotImplementedException($"{nop.reason}"); + } + + DicConsole.ErrorWriteLine($"{nop.reason}"); + LastError = nop.errno; + return false; + } } } \ No newline at end of file diff --git a/DiscImageChef.Devices/Remote/Structs.cs b/DiscImageChef.Devices/Remote/Structs.cs index 774bd7a6c..cd0bfb0c0 100644 --- a/DiscImageChef.Devices/Remote/Structs.cs +++ b/DiscImageChef.Devices/Remote/Structs.cs @@ -58,7 +58,7 @@ namespace DiscImageChef.Devices.Remote public struct DicPacketNop { public DicPacketHeader hdr; - public byte reasonCode; + public DicNopReason reasonCode; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] spare;