SSブログ

NuDCLその4 [Mac用USBデバイス工作]

NuDCLと古いDCLの使い方の違いのおさらいを続けている。思想は同じだけど使い勝手はけっこう違う。NuDCLは古いDCLに較べてずいぶんシンプルに整理されている。とはいってもI/O Kitなので使いこなすのはちょっと難しそうではある。

2.7  タイムスタンプ

FireWireのホストコントローラにはホスト側がパケットを受け取ったとき、そのパケットにタイムスタンプを打つ機能がある。バスサイクルが基準で、実時間になってないので使い勝手は悪いけど、リアルタイム性の必要なアプリ(例えばカメラの画像と他のハードウェアを同期させる)では便利な機能である。

古いDCLではタイムスタンプをとってくる専用のコマンドがあって
DCLCommand* (*AllocatePtrTimeStampDCL)(IOFireWireLibDCLCommandPoolRef self,
                                       DCLCommand* inDCL,
                                       UInt32* inTimeStampPtr);
で生成する。これが実行されるときにinTimeStampPtrがさしているメモリ領域にホストコントローラのタイムスタンプの値がコピーされる。ただし、このコマンドはupdateコマンドのあとでないと機能しない。

NuDCLではやはり専用のコマンドではなく
IOReturn    (*SetDCLTimeStampPtr)(NuDCLRef dcl,
                                  UInt32* timeStampPtr);
というプールの関数を使う。引数のdclは任意のコマンドでよく、dclが実行されるとtimeStampPtrの領域にタイムスタンプがコピーされる。

2.8  コールバック

DCLコマンドはスタティックなリンクトリストで、条件判定のようなコマンドはない。従ってループは無限ループしか作れない。条件判定してあるときにはループを脱出する、などと言ったコードはコールバックとしてCの関数を書いてそれを指定する。例えば、ループをしていてデータがいっぱいになったらいったんループを止め、データを退避して次のループを開始する、などという処理はデータがいっぱいになったかどうかをコールバック関数の中で判定し、ループの解除や再開になるようにDCLのリンクトリストを書き換える、というちょっと恐ろしいことをやる。

基本的には古いDCLもNuDCLも考え方は同じだけど、細部が微妙に違っている。

古いDLCではやはりコールバック関数指定専用のコマンドがある。
DCLCommand* (*AllocateCallProcDCL)(IOFireWireLibDCLCommandPoolRef self,
                                   DCLCommand* inDCL,
                                   DCLCallCommandProc* inProc,
                                   DCLCallProcDataType inProcData);
DCLコマンドのリンクトリストにこのコマンドが現れるとその時点でinProcで指定されたコールバック関数が呼ばれる。inProcDataはコールバック関数への引数として渡されるいわゆるRefConである。DCLCallCommandProcは
typedef void (DCLCallCommandProc)(DCLCommand * command);
となっている。これを見るとRefConが渡されていない。実はRefConは直接渡されるのではなく、コールバックコマンドの
typedef struct DCLCallProcStruct
{
    DCLCommand *            pNextDCLCommand;// Next DCL command.
    UInt32                  compilerData;   // Data for use by DCL compiler.
    UInt32                  opcode;         // DCL opcode.
    DCLCallCommandProc *    proc;           // Procedure to call.
    DCLCallProcDataType     procData;       // Data for use by called procedure.
} DCLCallProc;
procDataポインタが設定されているので例えば
    DCLCallProcStruct *pCallProc =  (DCLCallProcStruct*) pDCLCommand;
    UniversalReceiver *pReceiver = (UniversalReceiver*) pCallProc->procData;
のようにして取ってくる必要がある。
一方NuDCLではこれまでと同じように専用のコマンドというのはない。
typedef void (*NuDCLCallback)( void* refcon, NuDCLRef dcl);
IOReturn    (*SetDCLCallback)( NuDCLRef dcl,
                              NuDCLCallback callback);
という関数を使ってコールバック関数を指定する。こっちはちゃんと第1引数にRefConが入っている。

ただしこんどはSetDCLCallback関数にRefConを指定する引数がない。それはべつの関数
void    (*SetDCLRefcon)(NuDCLRef dcl, void* refcon);
を使って設定する。RefConはひとつのDCLコマンドごとに設定できる。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

献立07/01献立07/02 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。