気になること調査結果
 HOME > Programing > SPTIを利用してのDisc情報取得
LINK
 SPTIを利用してのDisc情報取得
SPTIとは

  SPTIとは、SCSI Pass Through Interfaceの略称で、SCSIデバイスを制御する
 インタフェースです。
  SPTIを用いるにはDDK(Driver Development Kits)が必要ですが、現在は、
 Microsoftのホームページからダウンロード出来ず、WindowsXPのDDKに限り、注文し、
 取り寄せることが出来るようです。

Disc情報を取得するには

  SPTIを利用し、Disc情報を取得する際には、デバイスドライバへコマンドを
 送信する必要があります。
  下記フローがコマンドを送信する際の基本的な手順になります。
  下記図中に、"コマンドを送信"とありますが、このコマンドを変更するだけで、
 多種多様な制御ができます。

Driveハンドルを取得
コマンドを送信
ハンドルを閉じる


コマンドとは?

  まずコマンドの打ち方ですが、下記のAPIをコールすることにより、
 デバイスドライバへ直接コマンド送信できます。

   BOOL DeviceIoControl(
     HANDLE       hDevice,          // デバイス、ファイル、ディレクトリいずれかのハンドル
     DWORD        dwIoControlCode,  // 実行する動作の制御コード
     LPVOID       lpInBuffer,       // 入力データを供給するバッファへのポインタ
     DWORD        nInBufferSize,    // 入力バッファのバイト単位のサイズ
     LPVOID       lpOutBuffer,      // 出力データを受け取るバッファへのポインタ
     DWORD        nOutBufferSize,   // 出力バッファのバイト単位のサイズ
     LPDWORD      lpBytesReturned,  // バイト数を受け取る変数へのポインタ
     LPOVERLAPPED lpOverlapped      // 非同期動作を表す構造体へのポインタ
   );

  SPTIでのコマンド指定は、以下の2パターンあります。

   (1)DeviceIoControl関数の第2引数に、直接コマンドを設定する。
   (2)DeviceIoControl関数の第3引数にあたる、SRB32_ExecSCSICmd構造体の
     sptメンバにコマンドを設定する。

	以下に、Drive・Discを制御する為の基本コマンドを列挙(私が知っている範囲で)します。
コマンド (1)の場合 (2)の場合
Drive Lock FSCTL_LOCK_VOLUME CDB[0]=0x1E
CDB[4]=0x01
Drive Unlock FSCTL_UNLOCK_VOLUME CDB[0]=0x1E
CDB[4]=0x00
Media Eject ON/OFF IOCTL_STORAGE_MEDIA_REMOVAL 不明
Volume Dismount FSCTL_DISMOUNT_VOLUME 不明
Drive Open IOCTL_STORAGE_EJECT_MEDIA CDB[0]=0x1B
CDB[1]=0x01
CDB[4]=0x20
Drive Close IOCTL_STORAGE_LOAD_MEDIA CDB[0]=0x1B
CDB[1]=0x01
CDB[4]=0x21
InquiryData取得 IOCTL_SCSI_GET_INQUIRY_DATA 不明
Capabilities取得 IOCTL_SCSI_GET_CAPABILITIES 不明
Drive情報取得 IOCTL_CDROM_GET_DRIVE_GEOMETRY 不明
Discタイプ取得 IOCTL_CDROM_DISK_TYPE CDB[0]=0x46
CDB[8]=8
Disc情報取得 不明 CDB[0]=0x51
CDB[7]=Disc情報サイズ
TOC情報取得 IOCTL_CDROM_READ_TOC CDB[0]=0x43
CDB[1]=0x02
CDB[2]=0x02
CDB[7]=session no.
CDB[8]=取得サイズ(byte)
Qサブコード取得 IOCTL_CDROM_READ_Q_CHANNEL CDB[0]=0xBE
CDB[2]-[5]=LBA
CDB[6]-[7]=取得セクタサイズ
CDB[10]=2
データ取得 IOCTL_CDROM_RAW_READ CDB[0]=0xBE
CDB[2]-[5]=LBA
CDB[6]-[7]=取得セクタサイズ
CDB[9]=0xF8




ディスク情報取得手順

 Disc情報を取得するには、以下の順番にコマンドを発行します。
  1. ドライブハンドルを取得する。
  2. ディスクタイプを取得する。
  3. ドライブをBlock(Prevent allow)する。
  4. セッション・トラック情報を取得する。
  5. ディスクに合わせて、最終LBAを確認する。
  6. 最終LBAまでリードする。
  7. ドライブをUnblock(Prevent allow)する。
  8. ドライブハンドルをクローズする。
ドライブハンドル取得

  ドライブハンドルの取得は、CreateFile関数にて行います。
 どうやってドライブハンドルを取得するの?と思う方もいらっしゃると思いますが、
 答えは簡単です。
  以下のように引数していすればハンドル取得できます。

   ファイル名          :"\\\\.\\ドライブレター:"
   アクセスモード        :GENERIC_WRITE|GENERIC_READ
   共有モード          :FILE_SHARE_WRITE
   セキュリティ記述子      :NULL
   作成方法           :OPEN_EXISTING
   ファイル属性         :0
   テンプレートファイルのハンドル:NULL


ディスクタイプ取得

  ディスクタイプの取得は、上記コマンドのDiscタイプ取得コマンドを利用します。
 ディスクタイプは、CD-ROM・CD-R・DVD-ROM・DVD-R・DVD-RAM・DVR-RW(フォーマット済み)・
 DVR-RW(シーケンシャル記録)・DVD+R・DVD+RWが取れます。

  DVD系は、最終セッションの最終LBAまで取得するだけで、全ディスク情報を取れます。
 DVD-RAMに関しては、最終LBAが読めない場合があるので、読めるLBAまで遡る必要が
 あるかもしれません。

  CD系のCD-ROMの場合は、TOC情報から総再生時間を取得し、この時間から最終LBAを取得すれば、
 全ディスク情報を取れます。
 それ以外のCDは、TOC情報から取れる総再生時間から最終LBAを算出すると、ファースト・
 セッションしか取得出来ないので、気を付けて下さい。


ドライブをBlock

  ドライブのBlockは、上記コマンドDrive lockで行います。
 特記するほどのことはない、簡単な手順ですが、重要です。


セッション・トラック情報取得

  DVD系の場合は、必須手順です。上記のDisc情報取得コマンドで取得出来ます。
 CD系の場合は、TOC情報を取得(付録参照)し、最終LBAを求めます。最終LBAは、
 TOC情報の内、
 POINT=0xA2のMIN・SEC・FRAMEをLBAに変換すれば取得出来ます。


最終LBA確認

  私もはっきりとしたところは分からないのですが、データCDや、DVD-RAMの場合、
 上記手順で取得した最終LBAはリード出来ず、もう少し遡ったLBAまでリード出来ない
 ことがあり、最終LBAのリードテストを行い、調整します。
  本当は、微調整する為の正式手順があるかも知れません。もし、ご存知の方が
 いらっしゃったら、教えてください!!


データをリード

  データのリードは、ファイルのリードとは違い、トラック毎のモードに合わせて
 コマンドを送信する必要があります。モードは、以下は通りです。

   ・AUDIO   :オーディオ
   ・CDG    :カラオケCD+G
   ・MODE1/2048:CDROM Mode1 DATA
   ・MODE1/2352:CDROM Mode1 DATA(RAW)
   ・MODE2/2336:CDROM Mode2 DATA
   ・MODE2/2352:CDROM Mode2 DATA(RAW)
   ・CDI/2336 :CDI Mode2 DATA
   ・CDI/2352 :CDI Mode2 DATA(RAW)

  上記のモード毎のコマンドでリードして下さい。
 (コマンドは分かり次第、コマンド表に記載予定です。)


ドライブをUnblock

	  ドライブのUnblockは、上記コマンドDrive unlockで行います。
	  特記するほどのことはない、簡単な手順ですが、これまた重要です。


ハンドルをクローズする

	  最後は、オープンしたハンドルを、CloseHandleでクローズします。
	 このへんは、ファイルI/Oと同じですね。


  ※現在、CD-DA情報の取得方法について調査中です。調査結果は、随時上げる
 つもりですので、暫くお待ち下さい。
 (その伏線として、付録だけ先にアップしておきます)
<付録>

CDROMのデータ構造

  CDROMのデータの最小単位はフレームで、このフレームを98ブロック集めたものを、
 サブコーディング・フレームといいます。
  これは、Qサブチャネルが98ビットで意味を持つ為です。
 CDROMのデータ構造では、このQサブチャネルのデータと、TOC(Table of Contents)の
 情報が非常に重要です。

TOC情報の構造

TNO

8
POINT

8
MIN

8
SEC

8
FRAME

8
ZERO

8
PMIN

8
PSEC

8
PFRAME

8

         TOC情報は、上記のようになっています。左から順に、

		・TNO  :トラック番号
		・POINT:0〜99:PMIN, PSEC, PFRAME は、各トラックの開始する絶対時間を示す。
		     A0H :PMIN は、最初のトラックのトラック番号を示す。PSEC、PFRAMEは0。
		     A1H :PMIN は、最終トラックのトラック番号を示す。PSEC、PFRAMEは0。
		     A2H :PMIN, PSEC, PFRAME は、リードアウトの始まる絶対時間を示す。
		・MIN :トラック先頭からの相対時間(分)を示す。
		・SEC :トラック先頭からの相対時間(秒)を示す。
		・FRAME:トラック先頭からの相対時間(フレーム)を示す。
		・ZERO :0。


Qサブコードの構造

TNO

8
INDEX

8
MIN

8
SEC

8
FRAME

8
ZERO

8
PMIN

8
PSEC

8
PFRAME

8

         Qサブコードは、上記のようになっています。左から順に、

		・TNO   :トラック番号
		・INDEX :無音部分:0。
		・MIN  :トラック先頭からの相対時間(分)を示す。
		・SEC  :トラック先頭からの相対時間(秒)を示す。
		・FRAME :トラック先頭からの相対時間(フレーム)を示す。
		・ZERO  :0。
		・PMIN  :Disc先頭からの絶対時間(分)を示す。
		・PSEC  :Disc先頭からの絶対時間(秒)を示す。
		・PFRAME:Disc先頭からの絶対時間(フレーム)を示す。

<質問・要望など>

    上記内容に対しての質問、要望などは常に受け付けております。
    以下のメールフォームか、掲示板へ書き込みをお願いします。

    メール送信フォーム
    掲示板


  アフィリエイトならこれ!

 ・バリューコマース

 ・アクセストレード


  PC・周辺機器買うならこれ!

 ・全国31店舗展開!BTOパソコンならドスパラへ!

Copyright(C) 2005 s. All right reserved.