/// <summary>Sends a SCSI command</summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="fd">File handle</param> /// <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 error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI /// sense /// </param> /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception> internal static int SendScsiCommand(object fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout, ScsiDirection direction, out double duration, out bool sense) { PlatformID ptId = DetectOS.GetRealPlatformID(); return(SendScsiCommand(ptId, fd, cdb, ref buffer, out senseBuffer, timeout, direction, out duration, out sense)); }
/// <summary>Sends a SCSI command to this 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> public int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout, ScsiDirection direction, out double duration, out bool sense) { if (!(_remote is null)) { return(_remote.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, direction, out duration, out sense)); } return(Command.SendScsiCommand(PlatformId, FileHandle, cdb, ref buffer, out senseBuffer, timeout, direction, out duration, out sense)); }
/// <summary>Sends a SCSI command</summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="ptId">Platform ID for executing the command</param> /// <param name="fd">File handle</param> /// <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 error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI /// sense /// </param> /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception> internal static int SendScsiCommand(PlatformID ptId, object fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout, ScsiDirection direction, out double duration, out bool sense) { switch (ptId) { case PlatformID.Win32NT: { ScsiIoctlDirection dir; switch (direction) { case ScsiDirection.In: dir = ScsiIoctlDirection.In; break; case ScsiDirection.Out: dir = ScsiIoctlDirection.Out; break; default: dir = ScsiIoctlDirection.Unspecified; break; } return(Windows.Command.SendScsiCommand((SafeFileHandle)fd, cdb, ref buffer, out senseBuffer, timeout, dir, out duration, out sense)); } case PlatformID.Linux: { Linux.ScsiIoctlDirection dir; switch (direction) { case ScsiDirection.In: dir = Linux.ScsiIoctlDirection.In; break; case ScsiDirection.Out: dir = Linux.ScsiIoctlDirection.Out; break; case ScsiDirection.Bidirectional: dir = Linux.ScsiIoctlDirection.Unspecified; break; case ScsiDirection.None: dir = Linux.ScsiIoctlDirection.None; break; default: dir = Linux.ScsiIoctlDirection.Unknown; break; } return(Linux.Command.SendScsiCommand((int)fd, cdb, ref buffer, out senseBuffer, timeout, dir, out duration, out sense)); } case PlatformID.FreeBSD: { CcbFlags flags = 0; switch (direction) { case ScsiDirection.In: flags = CcbFlags.CamDirIn; break; case ScsiDirection.Out: flags = CcbFlags.CamDirOut; break; case ScsiDirection.Bidirectional: flags = CcbFlags.CamDirBoth; break; case ScsiDirection.None: flags = CcbFlags.CamDirNone; break; } return(IntPtr.Size == 8 ? FreeBSD.Command.SendScsiCommand64((IntPtr)fd, cdb, ref buffer, out senseBuffer, timeout, flags, out duration, out sense) : FreeBSD.Command.SendScsiCommand((IntPtr)fd, cdb, ref buffer, out senseBuffer, timeout, flags, out duration, out sense)); } default: throw new InvalidOperationException($"Platform {ptId} not yet supported."); } }
public int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout, ScsiDirection direction, out double duration, out bool sense) { senseBuffer = null; duration = 0; sense = true; var cmdPkt = new AaruPacketCmdScsi { hdr = new AaruPacketHeader { remote_id = Consts.RemoteId, packet_id = Consts.PacketId, version = Consts.PacketVersion, packetType = AaruPacketType.CommandScsi }, direction = (int)direction, timeout = timeout * 1000 }; if (cdb != null) { cmdPkt.cdb_len = (uint)cdb.Length; } if (buffer != null) { cmdPkt.buf_len = (uint)buffer.Length; } cmdPkt.hdr.len = (uint)(Marshal.SizeOf <AaruPacketCmdScsi>() + cmdPkt.cdb_len + cmdPkt.buf_len); byte[] pktBuf = Marshal.StructureToByteArrayLittleEndian(cmdPkt); byte[] buf = new byte[cmdPkt.hdr.len]; Array.Copy(pktBuf, 0, buf, 0, Marshal.SizeOf <AaruPacketCmdScsi>()); if (cdb != null) { Array.Copy(cdb, 0, buf, Marshal.SizeOf <AaruPacketCmdScsi>(), cmdPkt.cdb_len); } if (buffer != null) { Array.Copy(buffer, 0, buf, Marshal.SizeOf <AaruPacketCmdScsi>() + cmdPkt.cdb_len, cmdPkt.buf_len); } 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.RemoteId || hdr.packet_id != Consts.PacketId) { AaruConsole.ErrorWriteLine("Received data is not an Aaru Remote Packet..."); return(-1); } if (hdr.packetType != AaruPacketType.ResponseScsi) { AaruConsole.ErrorWriteLine("Expected SCSI 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); } AaruPacketResScsi res = Marshal.ByteArrayToStructureLittleEndian <AaruPacketResScsi>(buf); senseBuffer = new byte[res.sense_len]; Array.Copy(buf, Marshal.SizeOf <AaruPacketResScsi>(), senseBuffer, 0, res.sense_len); buffer = new byte[res.buf_len]; Array.Copy(buf, Marshal.SizeOf <AaruPacketResScsi>() + res.sense_len, buffer, 0, res.buf_len); duration = res.duration; sense = res.sense != 0; return((int)res.error_no); }
/// <summary> /// Sends a SCSI command to this 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> public int SendScsiCommand(byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout, ScsiDirection direction, out double duration, out bool sense) => Command.SendScsiCommand(PlatformId, FileHandle, cdb, ref buffer, out senseBuffer, timeout, direction, out duration, out sense);