View Javadoc

1   package org.jscsi.target.scsi.sense;
2   
3   
4   import java.nio.ByteBuffer;
5   
6   import org.jscsi.target.scsi.sense.senseDataDescriptor.SenseDataDescriptor;
7   import org.jscsi.target.util.BitManip;
8   import org.jscsi.target.util.ReadWrite;
9   
10  
11  /**
12   * Instances of this class represent sense data using the descriptor format.
13   * 
14   * @see SenseDataFormat#DESCRIPTOR
15   * @author Andreas Ergenzinger
16   */
17  public final class DescriptorFormatSenseData extends SenseData {
18  
19      /**
20       * The length in bytes of all fixed fields of descriptor format sense data.
21       */
22      private static final int HEADER_LENGTH = 8;
23  
24      /**
25       * The byte position of the ADDITIONAL SENSE CODE field.
26       */
27      private static final int ADDITIONAL_SENSE_CODE_INDEX = 2;
28  
29      /**
30       * The position of the first reserved byte.
31       * 
32       * @see #RESERVED_BYTES_MAX_INDEX
33       */
34      private static final int RESERVED_BYTES_MIN_INDEX = 4;
35  
36      /**
37       * The position of the last reserved byte.
38       * 
39       * @see #RESERVED_BYTES_MIN_INDEX
40       */
41      private static final int RESERVED_BYTES_MAX_INDEX = 6;
42  
43      /**
44       * The position of the ADDITIONAL SENSE LENGTH field.
45       */
46      private static final int ADDITIONAL_SENSE_LENGTH_INDEX = 7;
47  
48      /**
49       * All sense data descriptors that are a part of this sense data object.
50       */
51      private final SenseDataDescriptor[] senseDataDescriptors;
52  
53      /**
54       * The constructor.
55       * 
56       * @param errorType the error type
57       * @param senseKey a general description of what caused the error
58       * @param additionalSenseCodeAndQualifier a more specific description of the error
59       * @param senseDataDescriptors more specific error information
60       */
61      public DescriptorFormatSenseData (final ErrorType errorType, final SenseKey senseKey, AdditionalSenseCodeAndQualifier additionalSenseCodeAndQualifier, SenseDataDescriptor... senseDataDescriptors) {
62          super(errorType, SenseDataFormat.DESCRIPTOR, senseKey, additionalSenseCodeAndQualifier);
63          this.senseDataDescriptors = senseDataDescriptors;
64      }
65  
66      public void serialize (ByteBuffer byteBuffer, int index) {
67  
68          byteBuffer.position(index);
69  
70          // response code and valid
71          byte b = (byte) getReponseCodeFor(errorType, SenseDataFormat.DESCRIPTOR);
72          b = BitManip.getByteWithBitSet(b, 7, false);// bit 7 is reserved
73          byteBuffer.put(b);// index
74  
75          // sense key
76          b = (byte) (senseKey.getValue() & 15);
77          byteBuffer.put(b);// index + 1
78  
79          // additional sense code and additional sense code qualifier
80          ReadWrite.writeTwoByteInt(byteBuffer, additionalSenseCodeAndQualifier.getValue(), index + ADDITIONAL_SENSE_CODE_INDEX);
81  
82          // bytes 4-6 are reserved
83          for (int i = index + RESERVED_BYTES_MIN_INDEX; i < index + RESERVED_BYTES_MAX_INDEX; ++i)
84              byteBuffer.put(i, (byte) 0);
85  
86          // additional sense length
87          byteBuffer.put(index + ADDITIONAL_SENSE_LENGTH_INDEX, (byte) getAdditionalSenseLength());
88  
89          // sense data descriptors
90          int descriptorIndex = HEADER_LENGTH;
91          for (int i = 0; i < senseDataDescriptors.length; ++i) {
92              if (senseDataDescriptors[i] != null) {
93                  senseDataDescriptors[i].serialize(byteBuffer, descriptorIndex);
94                  descriptorIndex += senseDataDescriptors[i].size();
95              }
96          }
97      }
98  
99      /**
100      * Returns the value of the ADDITIONAL SENSE LENGTH field.
101      * <p>
102      * This is the total length of all included {@link SenseDataDescriptor} objects.
103      * 
104      * @return the value of the ADDITIONAL SENSE LENGTH field
105      */
106     private int getAdditionalSenseLength () {
107         int additionalSenseLength = 0;
108         if (senseDataDescriptors != null) {
109             for (int i = 0; i < senseDataDescriptors.length; ++i)
110                 if (senseDataDescriptors[i] != null) additionalSenseLength += senseDataDescriptors[i].size();
111         }
112         return additionalSenseLength;
113     }
114 
115     public int size () {
116         return getAdditionalSenseLength()// is never negative
117                 + HEADER_LENGTH;
118     }
119 
120 }