/// <summary> /// Reads an attribute from the medium auxiliary memory /// </summary> /// <param name="buffer">Buffer.</param> /// <param name="senseBuffer">Sense buffer.</param> /// <param name="action">What to do, <see cref="ScsiAttributeAction" />.</param> /// <param name="volume">Volume number.</param> /// <param name="partition">Partition number.</param> /// <param name="firstAttribute">First attribute identifier.</param> /// <param name="cache">If set to <c>true</c> device can return cached data.</param> /// <param name="timeout">Timeout.</param> /// <param name="duration">Duration.</param> public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte volume, byte partition, ushort firstAttribute, bool cache, uint timeout, out double duration) => ReadAttribute(out buffer, out senseBuffer, action, 0, 0, volume, partition, firstAttribute, cache, timeout, out duration);
/// <summary> /// Reads an attribute from the medium auxiliary memory /// </summary> /// <param name="buffer">Buffer.</param> /// <param name="senseBuffer">Sense buffer.</param> /// <param name="action">What to do, <see cref="ScsiAttributeAction" />.</param> /// <param name="partition">Partition number.</param> /// <param name="firstAttribute">First attribute identifier.</param> /// <param name="timeout">Timeout.</param> /// <param name="duration">Duration.</param> public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte partition, ushort firstAttribute, uint timeout, out double duration) { return(ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, partition, firstAttribute, false, timeout, out duration)); }
/// <summary>Reads an attribute from the medium auxiliary memory, or reports which elements in the changer contain one</summary> /// <param name="buffer">Buffer.</param> /// <param name="senseBuffer">Sense buffer.</param> /// <param name="action">What to do, <see cref="ScsiAttributeAction" />.</param> /// <param name="element">Element address.</param> /// <param name="elementType">Element type.</param> /// <param name="volume">Volume number.</param> /// <param name="partition">Partition number.</param> /// <param name="firstAttribute">First attribute identificator.</param> /// <param name="cache">If set to <c>true</c> device can return cached data.</param> /// <param name="timeout">Timeout.</param> /// <param name="duration">Duration.</param> public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, ushort element, byte elementType, byte volume, byte partition, ushort firstAttribute, bool cache, uint timeout, out double duration) { buffer = new byte[256]; byte[] cdb = new byte[16]; senseBuffer = new byte[32]; cdb[0] = (byte)ScsiCommands.ReadAttribute; cdb[1] = (byte)((byte)action & 0x1F); cdb[2] = (byte)((element & 0xFF00) >> 8); cdb[3] = (byte)(element & 0xFF); cdb[4] = (byte)(elementType & 0x0F); cdb[5] = volume; cdb[7] = partition; cdb[8] = (byte)((firstAttribute & 0xFF00) >> 8); cdb[9] = (byte)(firstAttribute & 0xFF); cdb[10] = (byte)((buffer.Length & 0xFF000000) >> 24); cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16); cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[13] = (byte)(buffer.Length & 0xFF); if (cache) { cdb[14] += 0x01; } LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); Error = LastError != 0; if (sense) { return(true); } uint attrLen = (uint)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3] + 4); buffer = new byte[attrLen]; cdb[10] = (byte)((buffer.Length & 0xFF000000) >> 24); cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16); cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[13] = (byte)(buffer.Length & 0xFF); senseBuffer = new byte[32]; LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); Error = LastError != 0; AaruConsole.DebugWriteLine("SCSI Device", "READ ATTRIBUTE took {0} ms.", duration); return(sense); }
static void ReadAttribute(string devPath, Device dev) { ushort element = 0; byte elementType = 0; byte volume = 0; byte partition = 0; ushort firstAttribute = 0; bool cache = false; ScsiAttributeAction action = ScsiAttributeAction.Values; string strDev; int item; parameters: while (true) { System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("Parameters for READ ATTRIBUTE command:"); AaruConsole.WriteLine("Action: {0}", action); AaruConsole.WriteLine("Element: {0}", element); AaruConsole.WriteLine("Element type: {0}", elementType); AaruConsole.WriteLine("Volume: {0}", volume); AaruConsole.WriteLine("Partition: {0}", partition); AaruConsole.WriteLine("First attribute: {0}", firstAttribute); AaruConsole.WriteLine("Use cache?: {0}", cache); AaruConsole.WriteLine(); AaruConsole.WriteLine("Choose what to do:"); AaruConsole.WriteLine("1.- Change parameters."); AaruConsole.WriteLine("2.- Send command with these parameters."); AaruConsole.WriteLine("0.- Return to SCSI Media Changer commands menu."); strDev = System.Console.ReadLine(); if (!int.TryParse(strDev, out item)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); System.Console.ReadKey(); continue; } switch (item) { case 0: AaruConsole.WriteLine("Returning to SCSI Media Changer commands menu..."); return; case 1: AaruConsole.WriteLine("Attribute action"); AaruConsole.WriteLine("Available values: {0} {1} {2} {3} {4}", ScsiAttributeAction.Values, ScsiAttributeAction.List, ScsiAttributeAction.VolumeList, ScsiAttributeAction.PartitionList, ScsiAttributeAction.ElementList, ScsiAttributeAction.Supported); AaruConsole.Write("Choose?: "); strDev = System.Console.ReadLine(); if (!Enum.TryParse(strDev, true, out action)) { AaruConsole.WriteLine("Not a valid attribute action. Press any key to continue..."); action = ScsiAttributeAction.Values; System.Console.ReadKey(); continue; } AaruConsole.Write("Element?: "); strDev = System.Console.ReadLine(); if (!ushort.TryParse(strDev, out element)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); element = 0; System.Console.ReadKey(); continue; } AaruConsole.Write("Element type?: "); strDev = System.Console.ReadLine(); if (!byte.TryParse(strDev, out elementType)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); elementType = 0; System.Console.ReadKey(); continue; } AaruConsole.Write("Volume?: "); strDev = System.Console.ReadLine(); if (!byte.TryParse(strDev, out volume)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); volume = 0; System.Console.ReadKey(); continue; } AaruConsole.Write("Partition?: "); strDev = System.Console.ReadLine(); if (!byte.TryParse(strDev, out partition)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); partition = 0; System.Console.ReadKey(); continue; } AaruConsole.Write("First attribute?: "); strDev = System.Console.ReadLine(); if (!ushort.TryParse(strDev, out firstAttribute)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); firstAttribute = 0; System.Console.ReadKey(); continue; } AaruConsole.Write("Use cache?: "); strDev = System.Console.ReadLine(); if (!bool.TryParse(strDev, out cache)) { AaruConsole.WriteLine("Not a boolean. Press any key to continue..."); cache = false; System.Console.ReadKey(); } break; case 2: goto start; } } start: System.Console.Clear(); bool sense = dev.ReadAttribute(out byte[] buffer, out byte[] senseBuffer, action, element, elementType, volume, partition, firstAttribute, cache, dev.Timeout, out double duration); menu: AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("Sending READ ATTRIBUTE to the device:"); AaruConsole.WriteLine("Command took {0} ms.", duration); AaruConsole.WriteLine("Sense is {0}.", sense); AaruConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); AaruConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); AaruConsole.WriteLine("Sense buffer is {0} bytes.", senseBuffer?.Length.ToString() ?? "null"); AaruConsole.WriteLine("Sense buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(senseBuffer)); AaruConsole.WriteLine(); AaruConsole.WriteLine("Choose what to do:"); AaruConsole.WriteLine("1.- Print buffer."); AaruConsole.WriteLine("2.- Print sense buffer."); AaruConsole.WriteLine("3.- Decode sense buffer."); AaruConsole.WriteLine("4.- Send command again."); AaruConsole.WriteLine("5.- Change parameters."); AaruConsole.WriteLine("0.- Return to SCSI Media Changer commands menu."); AaruConsole.Write("Choose: "); strDev = System.Console.ReadLine(); if (!int.TryParse(strDev, out item)) { AaruConsole.WriteLine("Not a number. Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); goto menu; } switch (item) { case 0: AaruConsole.WriteLine("Returning to SCSI Media Changer commands menu..."); return; case 1: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("READ ATTRIBUTE response:"); if (buffer != null) { PrintHex.PrintHexArray(buffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); goto menu; case 2: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("READ ATTRIBUTE sense:"); if (senseBuffer != null) { PrintHex.PrintHexArray(senseBuffer, 64); } AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); goto menu; case 3: System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); AaruConsole.WriteLine("READ ATTRIBUTE decoded sense:"); AaruConsole.Write("{0}", Sense.PrettifySense(senseBuffer)); AaruConsole.WriteLine("Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); AaruConsole.WriteLine("Device: {0}", devPath); goto menu; case 4: goto start; case 5: goto parameters; default: AaruConsole.WriteLine("Incorrect option. Press any key to continue..."); System.Console.ReadKey(); System.Console.Clear(); goto menu; } }
/// <summary>Reads an attribute from the medium auxiliary memory</summary> /// <param name="buffer">Buffer.</param> /// <param name="senseBuffer">Sense buffer.</param> /// <param name="action">What to do, <see cref="ScsiAttributeAction" />.</param> /// <param name="firstAttribute">First attribute identifier.</param> /// <param name="timeout">Timeout.</param> /// <param name="duration">Duration.</param> public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, ushort firstAttribute, uint timeout, out double duration) => ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, 0, firstAttribute, false, timeout, out duration);