Send device open command packet.

This commit is contained in:
2019-10-13 22:29:09 +01:00
parent a83be0d5d6
commit ecad51de73
4 changed files with 147 additions and 54 deletions

View File

@@ -76,75 +76,78 @@ namespace DiscImageChef.Devices
remote = new Remote.Remote(host); remote = new Remote.Remote(host);
throw new NotImplementedException("Remote devices not yet implemented..."); Error = remote.Open(devicePath, out var errno);
LastError = errno;
} }
else
switch (PlatformId)
{ {
case PlatformID.Win32NT: switch (PlatformId)
{ {
FileHandle = Extern.CreateFile(devicePath, FileAccess.GenericRead | FileAccess.GenericWrite, case PlatformID.Win32NT:
FileShare.Read | FileShare.Write, IntPtr.Zero,
FileMode.OpenExisting,
FileAttributes.Normal, IntPtr.Zero);
if (((SafeFileHandle) FileHandle).IsInvalid)
{ {
Error = true; FileHandle = Extern.CreateFile(devicePath, FileAccess.GenericRead | FileAccess.GenericWrite,
LastError = Marshal.GetLastWin32Error(); FileShare.Read | FileShare.Write, IntPtr.Zero,
} FileMode.OpenExisting,
FileAttributes.Normal, IntPtr.Zero);
break; if (((SafeFileHandle) FileHandle).IsInvalid)
}
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
{ {
Error = true; Error = true;
LastError = Marshal.GetLastWin32Error();
} }
LastError = Marshal.GetLastWin32Error(); break;
} }
case PlatformID.Linux:
break;
}
case PlatformID.FreeBSD:
{
FileHandle = FreeBSD.Extern.cam_open_device(devicePath, FreeBSD.FileFlags.ReadWrite);
if (((IntPtr) FileHandle).ToInt64() == 0)
{ {
Error = true; FileHandle =
LastError = Marshal.GetLastWin32Error(); 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") var camDevice = (CamDevice) Marshal.PtrToStructure((IntPtr) FileHandle, typeof(CamDevice));
throw new
InvalidOperationException(
"Parallel ATA devices are not supported on FreeBSD due to upstream bug #224250.");
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."); if (Error) throw new SystemException($"Error {LastError} opening device.");

View File

@@ -8,4 +8,14 @@ namespace DiscImageChef.Devices.Remote
ResponseListDevices = 3, ResponseListDevices = 3,
CommandOpen = 4 CommandOpen = 4
} }
public enum DicNopReason : byte
{
OutOfOrder = 0,
NotImplemented = 1,
NotRecognized = 2,
ErrorListDevices = 3,
OpenOk = 4,
OpenError = 5
}
} }

View File

@@ -245,5 +245,85 @@ namespace DiscImageChef.Devices.Remote
return devices.ToArray(); 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<DicPacketCommandOpenDevice>(),
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<DicPacketHeader>()];
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<DicPacketHeader>(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<DicPacketNop>(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;
}
} }
} }

View File

@@ -58,7 +58,7 @@ namespace DiscImageChef.Devices.Remote
public struct DicPacketNop public struct DicPacketNop
{ {
public DicPacketHeader hdr; public DicPacketHeader hdr;
public byte reasonCode; public DicNopReason reasonCode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public readonly byte[] spare; public readonly byte[] spare;