| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| StandardInquiryData |
|
| 1.6;1.6 |
| 1 | package org.jscsi.target.scsi.inquiry; | |
| 2 | ||
| 3 | ||
| 4 | import java.nio.ByteBuffer; | |
| 5 | ||
| 6 | import org.jscsi.target.scsi.IResponseData; | |
| 7 | import org.jscsi.target.scsi.cdb.ScsiOperationCode; | |
| 8 | ||
| 9 | ||
| 10 | /** | |
| 11 | * The standard inquiry data, sent as a response to an {@link ScsiOperationCode#INQUIRY} command. | |
| 12 | * <p> | |
| 13 | * This class uses the singleton pattern since the returned standard inquiry data will always be the same. | |
| 14 | * <p> | |
| 15 | * Not all fields in the serialized form of the singleton have a corresponding member variable, only those fields | |
| 16 | * containing ASCII information. | |
| 17 | * | |
| 18 | * @author Andreas Ergenzinger | |
| 19 | */ | |
| 20 | public final class StandardInquiryData implements IResponseData { | |
| 21 | ||
| 22 | /** | |
| 23 | * The total length of the serialized Standard Inquiry Data. | |
| 24 | */ | |
| 25 | private static final int SIZE = 36; | |
| 26 | ||
| 27 | private static final String VENDOR_ID = "disyUKon"; | |
| 28 | private static final int VENDOR_ID_FIELD_POSITION = 8; | |
| 29 | private static final int VENDOR_ID_FIELD_LENGTH = 8; | |
| 30 | ||
| 31 | private static final String PRODUCT_ID = "jSCSI Target"; | |
| 32 | private static final int PRODUCT_ID_FIELD_POSITION = 16; | |
| 33 | private static final int PRODUCT_ID_FIELD_LENGTH = 16; | |
| 34 | ||
| 35 | private static final String PRODUCT_REVISION_LEVEL = "1.00"; | |
| 36 | private static final int PRODUCT_REVISION_LEVEL_FIELD_POSITION = 32; | |
| 37 | private static final int PRODUCT_REVISION_LEVEL_FIELD_LENGTH = 4; | |
| 38 | ||
| 39 | /** | |
| 40 | * The singleton. | |
| 41 | */ | |
| 42 | private static StandardInquiryData instance; | |
| 43 | ||
| 44 | 0 | private StandardInquiryData () { |
| 45 | // singleton pattern | |
| 46 | 0 | } |
| 47 | ||
| 48 | /** | |
| 49 | * Returns the one and only {@link StandardInquiryData} object. | |
| 50 | * | |
| 51 | * @return the one and only {@link StandardInquiryData} object | |
| 52 | */ | |
| 53 | public static StandardInquiryData getInstance () { | |
| 54 | 0 | if (instance == null) instance = new StandardInquiryData(); |
| 55 | 0 | return instance; |
| 56 | } | |
| 57 | ||
| 58 | public void serialize (ByteBuffer byteBuffer, int index) { | |
| 59 | ||
| 60 | // *** byte 0 **** | |
| 61 | /* | |
| 62 | * Peripheral qualifier (3 most significant bits of byte 0): 000b A peripheral device having the specified | |
| 63 | * peripheral device type is connected to this logical unit. If the device server is unable to determine whether | |
| 64 | * or not a peripheral device is connected, it also shall use this peripheral qualifier. This peripheral | |
| 65 | * qualifier does not mean that the peripheral device connected to the logical unit is ready for access. | |
| 66 | * Peripheral Device Type (5 least significant bits of byte 0): 00000b direct access block device Therefore no | |
| 67 | * need to change anything. | |
| 68 | */ | |
| 69 | 0 | byteBuffer.position(index); |
| 70 | 0 | byteBuffer.put((byte) 0); |
| 71 | ||
| 72 | // *** byte 1 *** | |
| 73 | /* | |
| 74 | * RMB bit (bit 7): 0 A removable medium (RMB) bit set to zero indicates that the medium is not removable. | |
| 75 | * (remaining bits are RESERVED) | |
| 76 | */ | |
| 77 | 0 | byteBuffer.put((byte) 0); |
| 78 | ||
| 79 | // *** byte 2 *** | |
| 80 | /* | |
| 81 | * version: 0x05 The device complies to the SPC3 and respective ANSI standard | |
| 82 | */ | |
| 83 | 0 | byteBuffer.put((byte) 0x05); |
| 84 | ||
| 85 | // *** byte 3 - flags *** | |
| 86 | /* | |
| 87 | * (bits 7 and 6 are obsolete) NORMACA (bit 5): 0 A NORMACA (normal auto contingency allegiance) bit set to zero | |
| 88 | * indicates that the device server does not support a NACA bit set to one and does not support the ACA task | |
| 89 | * attribute. HISUP (bit 4): 0 A hierarchical support (HISUP) bit set to zero indicates the SCSI target device | |
| 90 | * does not use the hierarchical addressing model to assign LUNs to logical units. RESPONSE DATA FORMAT (bits | |
| 91 | * 3-0): 0010b RESPONSE DATA FORMAT: SPC3 | |
| 92 | */ | |
| 93 | 0 | byteBuffer.put((byte) 2);// 0000 0010b |
| 94 | ||
| 95 | // *** byte 4 *** | |
| 96 | /* | |
| 97 | * n - 4 = 35 - 4 = 31 The ADDITIONAL LENGTH field indicates the length in bytes of the remaining standard | |
| 98 | * INQUIRY data. | |
| 99 | */ | |
| 100 | 0 | byteBuffer.put((byte) 31); |
| 101 | ||
| 102 | // *** byte 5 *** | |
| 103 | /* | |
| 104 | * SSCS (bit 7): 0 An SCC Supported bit set to zero indicates that the SCSI target device does not contain an | |
| 105 | * embedded storage array controller component. ACC (bit 6): 0 An ACC bit set to zero indicates that no access | |
| 106 | * controls coordinator may be addressed through this logical unit. TGPS field (bits 5 and 4): 00b The contents | |
| 107 | * of the target port group support (TPGS) indicate the support for asymmetric logical unit access. The SCSI | |
| 108 | * target device does not support asymmetric logical unit access or supports a form of asymmetric access that is | |
| 109 | * vendor specific. Neither the REPORT TARGET GROUPS nor the SET TARGET GROUPS commands is supported. 3PC (bit | |
| 110 | * 3): 0 A Third-Party Copy (3PC) bit set to zero indicates that the SCSI target device does not support | |
| 111 | * third-party copy commands such as the EXTENDED COPY command. (bits 2 and 1 are RESERVED) PROTECT (bit 0): 0 A | |
| 112 | * PROTECT bit set to zero indicates that the logical unit does not support protection information. | |
| 113 | */ | |
| 114 | 0 | byteBuffer.put((byte) 0); |
| 115 | ||
| 116 | // *** byte 6 *** | |
| 117 | /* | |
| 118 | * BQUE (bit 7): The CMDQUE bit and BQUE bit indicate whether the logical unit supports the full task management | |
| 119 | * model. 1 (and 0) Basic task management model supported. ENCSERV (bit 6): 0 An ENCSERV bit set to zero | |
| 120 | * indicates that the SCSI target device does not contain an embedded enclosure services component. (bit 5 is | |
| 121 | * VENDOR SPECIFIC i.e. 0) MULTIP (bit 4): 0 A Multi Port (MULTIP) bit set to zero indicates that this is not a | |
| 122 | * multi- port (two or more ports) SCSI target device and therefore does not conform to the SCSI multi-port | |
| 123 | * device requirements found in the applicable standards (e.g., SAM-3, a SCSI transport protocol standard and | |
| 124 | * possibly provisions of a command standard). MCHNGR (bit 3): 0 The MCHNGR bit is valid only when the RMB bit | |
| 125 | * is equal to one. A MCHNGR bit set to zero indicates that the SCSI target device does not support commands to | |
| 126 | * control an attached media changer. (bits 2 and 1 are RESERVED) ADDR16 (bit 0): 0 RESERVED since the SCSI | |
| 127 | * Parallel Interface transport protocol is not used. | |
| 128 | */ | |
| 129 | 0 | byteBuffer.put((byte) 128);// 1000 0000b |
| 130 | ||
| 131 | // *** byte 7 *** | |
| 132 | /* | |
| 133 | * (bits 7, 6, and 2 are OBSOLETE, bit 0 is VENDOR SPECIFIC) WBUS and SYNC (bits 5 and 4): 00b RESERVED since | |
| 134 | * the SCSI Parallel Interface transport protocol is not used. LINKED (bit 3): 0 A LINKED bit set to zero | |
| 135 | * indicates the device server does not support linked commands. CMDQUE (bit 1): 0 The CMDQUE bit and BQUE bit | |
| 136 | * indicate whether the logical unit supports the full task management model. (see BQUE ,byte 6) | |
| 137 | */ | |
| 138 | 0 | byteBuffer.put((byte) 0); |
| 139 | ||
| 140 | // *** bytes 8 to 15 *** | |
| 141 | /* | |
| 142 | * T10 VENDOR IDENTIFICATION: The T10 VENDOR IDENTIFICATION field contains eight bytes of left-aligned ASCII | |
| 143 | * data identifying the vendor of the product. The T10 vendor identification shall be one assigned by INCITS, | |
| 144 | * but obviously that is not the case here. disyUKon | |
| 145 | */ | |
| 146 | 0 | putString(byteBuffer, VENDOR_ID, index + VENDOR_ID_FIELD_POSITION, VENDOR_ID_FIELD_LENGTH); |
| 147 | ||
| 148 | // *** bytes 16 to 31 | |
| 149 | /* | |
| 150 | * PRODUCT IDENTIFICATION: The PRODUCT IDENTIFICATION field contains sixteen bytes of left-aligned ASCII data | |
| 151 | * defined by the vendor. | |
| 152 | */ | |
| 153 | 0 | putString(byteBuffer, PRODUCT_ID, index + PRODUCT_ID_FIELD_POSITION, PRODUCT_ID_FIELD_LENGTH); |
| 154 | ||
| 155 | // *** bytes 32 to 35 *** | |
| 156 | /* | |
| 157 | * PRODUCT REVISION LEVEL: The PRODUCT REVISION LEVEL field contains four bytes of left-aligned ASCII data | |
| 158 | * defined by the vendor. | |
| 159 | */ | |
| 160 | 0 | putString(byteBuffer, PRODUCT_REVISION_LEVEL, index + PRODUCT_REVISION_LEVEL_FIELD_POSITION, PRODUCT_REVISION_LEVEL_FIELD_LENGTH); |
| 161 | 0 | } |
| 162 | ||
| 163 | /** | |
| 164 | * Puts up to <i>fieldLength</i> of the passed {@link String} into a {@link ByteBuffer} and fills the remaining | |
| 165 | * bytes with zeros. | |
| 166 | * | |
| 167 | * @param byteBuffer where the {@link String}'s characters will be copied | |
| 168 | * @param string contains the characters to copy | |
| 169 | * @param position where the first character of the {@link String} will be put | |
| 170 | * @param fieldLength the number of bytes in the {@link ByteBuffer} that will be overwritten | |
| 171 | */ | |
| 172 | private void putString (final ByteBuffer byteBuffer, final String string, final int position, final int fieldLength) { | |
| 173 | // set position | |
| 174 | 0 | byteBuffer.position(position); |
| 175 | // put string characters | |
| 176 | 0 | final int stringLength = Math.min(string.length(), fieldLength); |
| 177 | 0 | for (int i = 0; i < stringLength; ++i) |
| 178 | 0 | byteBuffer.put((byte) string.charAt(i)); |
| 179 | // clear remaining remaining bytes | |
| 180 | 0 | for (int i = stringLength; i < fieldLength; ++i) |
| 181 | 0 | byteBuffer.put((byte) 0); |
| 182 | 0 | } |
| 183 | ||
| 184 | public int size () { | |
| 185 | 0 | return SIZE; |
| 186 | } | |
| 187 | } |