Projekte > Optische Laufwerke > Schublade

Status

Manchen interessiert es, ob die Schublade geöffnet oder geschlossen ist. Es gab zu der Sinnhaftigkeit dieser Frage einige Themen in verschiedenen Foren.

In der TIsoLib fand ich die Deklaration des Mechanism Status Header, welche eine Variable Door open enthält. Diesen Header erhält man, wenn man das MECHANISM STATUS Command aus den Multi Media Commands 5 Kapitel 6.11 oder 6 Kapitel 6.10 ausführt. Dafür wird die Funktion DeviceIoControl mit dem Controlcode IOCTL_SCSI_PASS_THROUGH_DIRECT (siehe auch GET_SCSI_PASS_THROUGH_DIRECT) und der entsprechenden Struktur ausgeführt. Der Command Descriptor Block sieht zum Beispiel so aus:

  7 6 5 4 3 2 1 0
0 Operation Code ($BD)
1 Reserviert
2 Reserviert
3 Reserviert
4 Reserviert
5 Reserviert
6 Reserviert
7 Reserviert
8 Allocation Length = $20
9
10 Reserviert
11 Control

 

Neben den Operation Code muss nur die Allocation Lenght, das heißt die Länge der Antwortstruktur angegeben werden. Die Antwortstruktur ist die Mechanism Status Parameter List. Diese sieht so aus:

  7 6 5 4 3 2 1 0
0..7 Mechanism Status Header
8..n Slot Tables

 

Der Mechanism Status Header

  7 6 5 4 3 2 1 0
0 Fault Changer State Current Slot (Untere 5 Bits)
1 Mechanism State Door open Reserved Current Slot (Obere 3 Bits)
2 Current LBA
3
4
5 Number of Slots Available
6 Lenght of Slot Tables
7

 

Dem Mechanism Status Header können bis zu 255 Slot tables folgen.

Die Deklaration und Ausführung könnte zum Beispiel so aussehen:

 
  type
    TMechanismStatusHeader = record
      Fault                   : Boolean;
      ChangerState            : Byte;
      CurrentSlot             : Byte;
      MechanismState          : Byte;
      DoorOopen               : Boolean;
      CurrentLBA              : Array[0..2] of Byte;
      NumberOfSlotsAvailable  : Byte;
      LengthOfSlotTables      : Word;
    end;
 
  function TOptDrives.GetDriveDoor: Integer;
  {*******************************************************************************
  *  Status der Schublade - geschlossen/geöffnet. Auf Basis der TISOLib
  }
  type
    TData = record
      Header : Array[0..7] of Byte;
      Data   :Array[0..0] of Byte;
  end;
  PData = ^TData;
  var
    hDevice    : THandle;
    aCDB       : Array of Byte;
    pBuffer    : PData;
    MechStatus : TMechanismStatusHeader;
  begin
    {
    *  Init
    }
    Result := -1;
    FillChar(MechStatus, SizeOf(MechStatus), #0);
    {
    *  Das Handle auf das Laufwerk holen.
    }
    hDevice := DriveHandleReadWrite;
    {
    *  Bei einem gültigen Handle Wert Struktur füllen und Befehl senden.
    }
    if hDevice <> INVALID_HANDLE_VALUE
    then begin
      SetLength(aCDB, CDB12GENERIC_LENGTH);
      aCDB[0] := SCSIOP_MECHANISM_STATUS;
      aCDB[8] := HiByte(SizeOf(TMechanismStatusHeader));
      aCDB[9] := LoByte(SizeOf(TMechanismStatusHeader));
      {
      *  Befehl ausführen. Manchmal ist es notwendig, den Speicher anzufordern.
      }
      GetMem(pBuffer, SizeOf(TMechanismStatusHeader));
      if GET_SCSI_PASS_THROUGH_DIRECT(hDevice, aCDB, pBuffer,
                            SizeOf(TMechanismStatusHeader))
      then begin
        ...
        MechStatus.DoorOopen := (pBuffer.Header[1] and $10) > 0;
        ...
        {
        *  Door open?
        }
        if MechStatus.DoorOopen
        then Result := 1
        else Result := 0;
      end;
      CloseHandle(hDevice);
    end;
  end;
          

Das Ergebnis -1 bedeutet Abruf fehlgeschlagen, 0 ist geschlossen und 1 geöffnet.

In diesem Zusammenhang ist es interessant wie die Schublade ausgeführt ist. Dazu sieht man sich die Capabilities an.

Demo:

Tray State (podTrayState.7z - 242 kb) MD5 (1 kb). Stand: 28. April 2013

Änderungen an der Demo

Datum Beschreibung
28.04.2013Kleine Überarbeitung und neuer Name.
09.04.2013Überarbeitung.