Projekte > Optische Laufwerke > Merkmale

Merkmale (Feature)

Nachdem man die Laufwerke und deren Bezeichnungen bestimmt hat, möchte man vermutlich wissen, welche Merkmale diese Laufwerke besitzen bzw. unterstützen. Um diese zu ermitteln, werden die SCSI Multi Media Commands verwendet. Um sie ausführen zu können wird das SCSI Pass Through Interface (SPTI) verwendet. Dafür wird in den Demos die Funktion GET_SCSI_PASS_THROUGH_DIRECT verwendet.

Die Drafts der SCSI Multi Media Commands sind bei T10 verfügbar. Man benötigt dafür einen Gastzugang, für welchen man sich registrieren muss. Das bedeutet, man gibt Vor- und Zunamen, Firma und Email an. Nach dem Akzeptieren der Notification und dem Klick auf Submit sollte die Datei angezeigt werden.

Aktuell ist das MultiMedia Command Set - 6 (MMC-6) Revision 02g vom 11.12.2009, für welches es keinen Direktlink mehr zu geben scheint. Dazu kommen die Änderungen MultiMedia Command Set - 6 Amendment # 1 (MMC-6 AM1) Revision 00 vom 6.12.2011.

Die Liste der Merkmale und die Eigenschaften der einzelnen Merkmale werden mit dem GET CONFIGURATION Command ermittelt.

GET CONFIGURATION Command - Operation Code $46

Das GET CONFIGURATION Command verwendet einen Command Descriptor Block (CDB), welcher immer zehn Byte lang ist. Für die Feature List sieht er so aus:

  7 6 5 4 3 2 1 0
0 Operation Code ($46)
1 Reserviert RT = 00b
2 Starting Feature Number = $0000
3
4 Reserviert
5
6
7 Allocation Length = $1007
8
9 Control

 

Die Werte:

Byte 0 Operation Code - $46 GET CONFIGURATION Command

Byte 1 Request Type (RT) - 00b Liste aller Feature

Wert Beschreibung
00b Das Laufwerk soll den Feature Header und alle durch das Laufwerk unterstützten Feature Beschreibungen zurückgeben ohne Rücksicht auf Geltung.
01b Das Laufwerk soll den Feature Header und nur die gewählte Feature Beschreibung zurückgeben.
10b Das Laufwerk soll den Feature Header und nur die gewählte Feature Beschreibung zurückgeben. Wird das Feature nicht unterstützt, soll nur der Feature Header zurückgegeben werden.
11b Reserviert

 
Byte 2 und 3 Starting Feature Number - $0000 Nummer des Features, welches zuerst ausgegeben werden soll. Da alle angezeigt werden sollen, wird die niedrigste mögliche Nummer angegeben.

Byte 7 und 8 Allocation Length - $1007: Länge der Antwortstruktur. Die Länge muss mindestens so groß gewählt werden, dass die erwartete Antwort auf jeden Fall hineinpasst. Nach welcher Formel man die Größe berechnen kann, habe ich noch nicht ausprobiert. Irgendwo habe ich den Wert $1007 gefunden, mit welchem die Ausführung funktioniert. Wählt man einen falschen Wert, bekommt man den Fehler Falscher Parameter.

Byte 9: Control - ?
 

Die Antwort besteht aus dem Feature Header:

  7 6 5 4 3 2 1 0
0 Data Length
1
2
3
4 Reserviert
5
6 Current Profile
7

 
Data Length - Die Datenlänge im Header gibt die Länge des noch folgenden Headerrestes und der Feature Beschreibungen an. Der Wert ist ein Vielfaches von vier.
 
Current Profile - Gibt das aktive Profil an. Das Profil ist vom Laufwerk und dem eingelegten Datenträger abhängig. Sind mehrere Profile aktiv wird das Profil mit der höchsten Nummer angegeben. (Liste der Profile in einem Fenster öffnen.)
 
Feature List - Ist die Data Length größer als vier schließt sich dem Header die Liste der Beschreibungen der unterstützten Feature an. Die Feature Beschreibungen beginnen mit diesen Header:

  7 6 5 4 3 2 1 0
0 Feature Code
1
2 Reserviert Version Persistent Current
3 Additional Length
4..n Featureabhängige Daten

 

Feature Code - Gibt die Nummer des unterstützen Features, dessen Beschreibung nun folgt, an. Einige Feature Beschreibungen sind auf diesen Seiten beschrieben:

Version - Die Versionsnummer des Features. Sie ändert sich, wenn die Beschreibung in der Entwicklung der Spezifikation geändert wird.

Persistent und Current geben an, ob das Feature geändert werden kann und ob es zur Zeit aktiv ist.

Additional Length - Die Länge der folgenden Beschreibung. Der Wert ist ein vielfaches von vier.
 

Deklarationen

 
  const
    SCSIOP_GET_CONFIGURATION = $46;
    FEATURE_PROFILE_LIST     = $0000;
    RT_All                   = 0;
    RT_Current               = 1;
    RT_Identified            = 2;
 
  type
    TGET_CONFIGURATION_CDB = record
      OperationCode         : Byte;
      RequestType           : Byte;
      StartingFeatureNumber : Word;
      AllocationLength      : Word;
    end;
 
  type
    TGET_CONFIGURATION_LIST = record
      Header : array[0..$07] of Byte;
      Data   : array[0..$0FFF] of Byte;
    end;
 
  type
    TGetConfigurationHeader = record
      DataLength     : Cardinal;
      CurrentProfile : Word;
    end;
 
    TFeature = record
      FeatureCode : Word;
      Version     : Byte;
      Persistent  : Boolean;
      Current     : Boolean;
    end;
 
  var
    FeatureList : array of TFeature;
 
          

 

Ausführung

Beispielfunktion. Dort wird erst der spezifische Command Descriptur Block gefüllt und dann in ein Array übertragen. Anschließend wird der Befehl ausgeführt und es werden die Feature Header ausgewertet. Die Feature Beschreibungen werden hier nicht ausgewertet sondern nur übersprungen.

 
  function TOptDrives.ReadConfigFeatureList(aDevice: THandle): Boolean;
  {
  {*******************************************************************************
  *  GET CONFIGURATION Feature List
  }
  var
    GET_CONF_CDB  : TGET_CONFIGURATION_CDB;
    GET_CONF_LIST : TGET_CONFIGURATION_LIST;
    aCDB          : Array of Byte;
    nByte         : Integer;
    nFeature      : Integer;
    nLength       : Integer;
  begin
    Result := False;
    {
    *  Configuration Header und Feature Core initialisieren.
    }
    FillChar(FDrive[FActive].ConfigHeader, SizeOf(TGetConfigurationHeader), $00);
    SetLength(FDrive[FActive].FeatureList, 0);
    {
    *  Den Command Descriptor Block füllen.
    }
    ZeroMemory(@GET_CONF_CDB, SizeOf(TGET_CONFIGURATION_CDB));
    GET_CONF_CDB.OperationCode         := SCSIOP_GET_CONFIGURATION;
    GET_CONF_CDB.RequestType           := RT_All;
    GET_CONF_CDB.StartingFeatureNumber := FEATURE_PROFILE_LIST;
    GET_CONF_CDB.AllocationLength      := SizeOf(TGET_CONFIGURATION_LIST);
    {
    *  Den Command Descriptor Block eintragen.
    }
    SetLength(aCDB, 10);
    aCDB[0] := GET_CONF_CDB.OperationCode;
    aCDB[1] := GET_CONF_CDB.RequestType;
    aCDB[2] := HiByte(GET_CONF_CDB.StartingFeatureNumber);
    aCDB[3] := LoByte(GET_CONF_CDB.StartingFeatureNumber);
    aCDB[7] := HiByte(GET_CONF_CDB.AllocationLength);
    aCDB[8] := LoByte(GET_CONF_CDB.AllocationLength);
    {
    *  Befehl ausführen
    }
    ZeroMemory(@GET_CONF_LIST, SizeOf(TGET_CONFIGURATION_LIST));
    Result := GET_SCSI_PASS_THROUGH_DIRECT(aDevice, aCDB, @GET_CONF_LIST,
                                           SizeOf(TGET_CONFIGURATION_LIST));
    if Result
    then begin
      FDrive[FActive].ConfigHeader.DataLength :=
            GET_CONF_LIST.Header[0] shl 24 or GET_CONF_LIST.Header[1] shl 16 or
            GET_CONF_LIST.Header[2] shl  8 or GET_CONF_LIST.Header[3];
      FDrive[FActive].ConfigHeader.CurrentProfile :=
            GET_CONF_LIST.Header[6] shl 8 or GET_CONF_LIST.Header[7];
      {
      *  Solange nicht gelesene Beschreibungen existieren.
      *  Die vier Byte sind der Rest vom Header.
      }
      nByte := 0;
      while FDrive[FActive].ConfigHeader.DataLength > nByte + 4
      do begin
        nFeature := Length(FDrive[FActive].FeatureList);
        SetLength(FDrive[FActive].FeatureList, nFeature + 1);
        with FDrive[FActive].FeatureList[nFeature]
        do begin
          FeatureCode := GET_CONF_LIST.Data[nByte + 0] shl 8 or
                         GET_CONF_LIST.Data[nByte + 1];
          Version     := GET_CONF_LIST.Data[nByte + 2] and $3C shr 2;
          Persistent  := GET_CONF_LIST.Data[nByte + 2] and $02 > 0;
          Current     := GET_CONF_LIST.Data[nByte + 2] and $01 > 0;
        end;
        nLength := GET_CONF_LIST.Data[nByte + 3] + 4;
        inc(nByte, nLength);
      end;
      {
      *  Ergebnis
      }
      Result := Length(FDrive[FActive].FeatureList) > 0;
    end;
  end;
          

 

Eine Demo mit der Funktion:

Feature List (podFeatureList.7z - 260 kb) MD5 (1 kb). Stand: 2. Juni 2013

Änderungen an der Demo

Datum Beschreibung
02.06.2013Kleine Überarbeitung und neuer Name.
27.01.2012Fehler: Beim Speichern war eine Änderung nicht übernommen worden.