StandardInquiryData.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* Copyright (C) 2012-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. namespace SCSI
  12. {
  13. public class StandardInquiryData
  14. {
  15. public byte PeripheralQualifier;
  16. public PeripheralDeviceType PeripheralDeviceType;
  17. public bool RMB; // Removable media bit
  18. public byte Version; // We only support Version == 2
  19. public bool NormACA; // Normal ACA Supported
  20. public bool HiSup; // Hierarchical Support
  21. public byte ResponseDataFormat;
  22. public byte AdditionalLength; // Number of bytes following this byte
  23. public bool SCCS; // SCC Supported
  24. public bool ACC; // Access Controls Coordinator
  25. public byte TPGS; // Target Port Group Support
  26. public bool ThirdPartyCopy; // 3PC
  27. public bool Protect;
  28. public bool EncServ; // Enclosure Services
  29. public bool VS1; // Vendor specific
  30. public bool MultiP; // Multi Port
  31. public bool MChngr; // Medium Changer
  32. public bool Addr16; // Indicates that the SCSI target device supports 16-bit wide SCSI addresses
  33. public bool WBus16; // Indicates that the SCSI target device supports 16-bit wide data transfers
  34. public bool Sync; // Indicates that the SCSI target device supports synchronous data transfer
  35. public bool CmdQue; // Command Queuing
  36. public bool VS2; // Vendor specific
  37. /// <summary>
  38. /// 8 characters
  39. /// </summary>
  40. public string VendorIdentification;
  41. /// <summary>
  42. /// 16 characters
  43. /// </summary>
  44. public string ProductIdentification;
  45. /// <summary>
  46. /// 4 characters
  47. /// </summary>
  48. public string ProductRevisionLevel;
  49. public ulong DriveSerialNumber;
  50. // Vendor Unique
  51. public byte Clocking;
  52. public bool QAS;
  53. public bool IUS;
  54. public List<VersionDescriptorName> VersionDescriptors = new List<VersionDescriptorName>(); // 8 descriptors (16 bytes)
  55. public StandardInquiryData()
  56. {
  57. ResponseDataFormat = 2;
  58. AdditionalLength = 91;
  59. }
  60. public StandardInquiryData(byte[] buffer, int offset)
  61. {
  62. PeripheralQualifier = (byte)(buffer[offset + 0] >> 5);
  63. PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F);
  64. RMB = (buffer[offset + 1] & 0x80) != 0;
  65. Version = buffer[offset + 2];
  66. if (Version != 2)
  67. {
  68. return;
  69. }
  70. NormACA = (buffer[offset + 3] & 0x20) != 0;
  71. HiSup = (buffer[offset + 3] & 0x10) != 0;
  72. ResponseDataFormat = (byte)(buffer[offset + 3] & 0x0F);
  73. AdditionalLength = buffer[offset + 4];
  74. if (AdditionalLength < 91) // Standard Inquiry data should be at least 96 bytes (so the AdditionalLength must be at least 96 - 5)
  75. {
  76. return;
  77. }
  78. SCCS = (buffer[offset + 5] & 0x80) != 0;
  79. ACC = (buffer[offset + 5] & 0x40) != 0;
  80. TPGS = (byte)((buffer[offset + 5] >> 4) & 0x03);
  81. ThirdPartyCopy = (buffer[offset + 5] & 0x08) != 0;
  82. Protect = (buffer[offset + 5] & 0x01) != 0;
  83. EncServ = (buffer[offset + 6] & 0x40) != 0;
  84. VS1 = (buffer[offset + 6] & 0x20) != 0;
  85. MultiP = (buffer[offset + 6] & 0x10) != 0;
  86. MChngr = (buffer[offset + 6] & 0x08) != 0;
  87. Addr16 = (buffer[offset + 6] & 0x01) != 0;
  88. WBus16 = (buffer[offset + 7] & 0x20) != 0;
  89. Sync = (buffer[offset + 7] & 0x10) != 0;
  90. CmdQue = (buffer[offset + 7] & 0x02) != 0;
  91. VS2 = (buffer[offset + 7] & 0x01) != 0;
  92. VendorIdentification = Encoding.ASCII.GetString(buffer, 8, 8);
  93. ProductIdentification = Encoding.ASCII.GetString(buffer, 16, 16);
  94. ProductRevisionLevel = Encoding.ASCII.GetString(buffer, 32, 4);
  95. DriveSerialNumber = BigEndianConverter.ToUInt64(buffer, 36);
  96. Clocking = (byte)((buffer[offset + 56] >> 2) & 0x03);
  97. QAS = (buffer[offset + 56] & 0x02) != 0;
  98. IUS = (buffer[offset + 56] & 0x01) != 0;
  99. for (int index = 0; index < 8; index++)
  100. {
  101. VersionDescriptorName versionDescriptor = (VersionDescriptorName)BigEndianConverter.ToUInt16(buffer, offset + 58 + index * 2);
  102. VersionDescriptors.Add(versionDescriptor);
  103. }
  104. }
  105. public byte[] GetBytes()
  106. {
  107. byte[] buffer = new byte[96];
  108. buffer[0] |= (byte)(PeripheralQualifier << 5);
  109. buffer[0] |= (byte)(PeripheralQualifier & 0x1F);
  110. if (RMB)
  111. {
  112. buffer[1] |= 0x80;
  113. }
  114. buffer[2] = Version;
  115. if (NormACA)
  116. {
  117. buffer[3] |= 0x20;
  118. }
  119. if (HiSup)
  120. {
  121. buffer[3] |= 0x10;
  122. }
  123. buffer[3] |= (byte)(ResponseDataFormat & 0x0F);
  124. buffer[4] = AdditionalLength;
  125. if (SCCS)
  126. {
  127. buffer[5] |= 0x80;
  128. }
  129. if (ACC)
  130. {
  131. buffer[5] |= 0x40;
  132. }
  133. buffer[5] |= (byte)((TPGS & 0x03) << 4);
  134. if (ThirdPartyCopy)
  135. {
  136. buffer[5] |= 0x08;
  137. }
  138. if (Protect)
  139. {
  140. buffer[5] |= 0x01;
  141. }
  142. if (EncServ)
  143. {
  144. buffer[6] |= 0x40;
  145. }
  146. if (VS1)
  147. {
  148. buffer[6] |= 0x20;
  149. }
  150. if (MultiP)
  151. {
  152. buffer[6] |= 0x10;
  153. }
  154. if (MChngr)
  155. {
  156. buffer[6] |= 0x08;
  157. }
  158. if (Addr16)
  159. {
  160. buffer[6] |= 0x01;
  161. }
  162. if (WBus16)
  163. {
  164. buffer[7] |= 0x20;
  165. }
  166. if (Sync)
  167. {
  168. buffer[7] |= 0x10;
  169. }
  170. if (CmdQue)
  171. {
  172. buffer[7] |= 0x02;
  173. }
  174. if (VS2)
  175. {
  176. buffer[7] |= 0x01;
  177. }
  178. ByteWriter.WriteAnsiString(buffer, 8, VendorIdentification, 8);
  179. ByteWriter.WriteAnsiString(buffer, 16, ProductIdentification, 16);
  180. ByteWriter.WriteAnsiString(buffer, 32, ProductRevisionLevel, 4);
  181. BigEndianWriter.WriteUInt64(buffer, 36, DriveSerialNumber);
  182. buffer[56] |= (byte)((Clocking & 0x03) << 2);
  183. if (QAS)
  184. {
  185. buffer[56] |= 0x02;
  186. }
  187. if (IUS)
  188. {
  189. buffer[56] |= 0x01;
  190. }
  191. for (int index = 0; index < 8; index++)
  192. {
  193. ushort versionDescriptor = 0;
  194. if (index < VersionDescriptors.Count)
  195. {
  196. versionDescriptor = (ushort)VersionDescriptors[index];
  197. }
  198. BigEndianWriter.WriteUInt16(buffer, 58 + index * 2, versionDescriptor);
  199. }
  200. return buffer;
  201. }
  202. }
  203. }