SSブログ

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

I/O KitというMacOS Xのハードウェアアクセス用のFrameworkが装備しているFireWire(IEEE1394)のアイソクロナス転送をサポートするためのNuDCLというメカニズムの勉強のため、AppleのサンプルコードであるUniversalReceiver.cppのソースを見てきた。

前回、NuDCLから呼ばれるOverrunDCLCallBack関数なんかを見た。overrunコールバックではようするにデータを取りこぼしたらすっぱり全部やり直す、ということをしていた。そんなんでええのんかいな。今日は残ったメンバ関数を見る。

3.9  stopReceive関数

これは全部を見てもたいしたことはやってない。

UniversalReceiver::stopReceive(void)
{
	IOReturn result = kIOReturnSuccess ;
    pthread_mutex_lock(&transportControlMutex);

    if (transportState == kUniversalReceiverTransportStopped) {
        pthread_mutex_unlock(&transportControlMutex);
        return kIOReturnExclusiveAccess;
    }
    finalizeCallbackCalled = false;
    stopNoDataTimer();
	
    result = (*isochChannel)->Stop(isochChannel);
    (*isochChannel)->ReleaseChannel(isochChannel);

    transportState = kUniversalReceiverTransportStopped;
	
    pthread_mutex_unlock(&transportControlMutex);
	
    if (result == kIOReturnSuccess)
        while (finalizeCallbackCalled == false)
            usleep(1000);
    return result;
}
finalizeCallbackCalledというフラグを設定してそれがtrueになるまで待っている。このフラグは
void UniversalReceiver::UniversalReceiveFinalizeCallback(void)
{
    finalizeCallbackCalled = true;
}
というコールバックの中で設定されている。このコールバックはそれ以外には何もしていないが、転送を止めたあとになにか整理する必要があればここに書けばいい、ということになる。

3.10  デストラクタ

デストラクタは特に変わった処理はしていない。単に確保したオブジェクトやメモリ領域を解放しているだけである。

簡単に手順を書いておくと
  1. stopReceive関数を呼ぶ
  2. CFRunLoopからコールバックのディスパッチャを取り除く
  3. 通知を止める
  4. チャンネルをリリースする
  5. ポートをリリースする
  6. DCLPoolをリリースしてupdate用の集合オブジェクトを破棄する
  7. バッファに使っていたメモリ領域を解放する
  8. ミューテクスロックを破棄する
である。特にどうと言うことはない。

3.11  その他のクライアントへのコールバック関数

クライアントオブジェクト側にデータを渡すためにコールバック関数を使っているが、UnversalReceiverではそれ以外の情報をクライアント側に伝えるためにもコールバックを定義している。

3.11.1  データが来ない

UniversalReceiverでは内部でタイマがセットされていて、データがくればそのタイマを先延ばしにしている。従ってタイマが起動されたといことはある一定時間データが来なかった、ということになる。このタイマが起動するとこのコールバックが呼ばれる。
typedef IOReturn (*UniversalNoDataProc)(void *pRefCon);
クライアント側はこれが呼ばれるとデバイス側を確認するなどを行う。そもそも繋がっていなければチャンネルなどは生成できないので、これが呼ばれるということは例えば
  • アイソクロナスチャンネルの設定が違っている
  • 転送速度の設定が違っている
などが考えられる。

3.11.2  リモートポート用のコールバック

リモートポートに転送の開始や終了などを指示するコールバックがある。

これはUniversalReceiverに限ったことではなく、FireWireのドキュメントにある。古いDCLのときもまったく同じものを書いた。

3.11.3  finalize

これはクライアント側へのコールバックではない。最後の片付けのためにローカルポートから呼ばれる。UniversalReceiverでは自分の内部で完結していて、実際にはスレッドの終了をこのコールバックが呼ばれるまで待つだけで、実質的になにもしていない。

しかし、こういうのはクライアント側にも解放したほうがいいと思われる。

3.11.4  メッセージ

エラーなどは別途ロガーを持っているがそれ以外にパケットのサイズが矛盾しているなど、エラーとして止めても、あるいは無視して継続してもいいというような場合に呼ばれる。クライアントにポリシを持って判断してもらおう、というものである。
typedef void (*UniversalReceiverMessageProc)(UInt32 msg,
                                             UInt32 param1,
                                             UInt32 param2,
                                             void *pRefCon);
ひとつめの引数はメッセージのタイプを表している。ふたつめみっつめの引数はよくわからない。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

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

トラックバック 0

献立07/31献立08/01 ブログトップ

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