SSブログ

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

FireWireのアイソクロナス転送でデータをやりとりするためのMacOS XのI/O KitによるメカニズムであるDCLを使ったAppleのサンプルコードのアイソクロナス転送をするC++クラスであるUniversalReceiverのメンバ関数の中身を見ている。今日はその続き。

3.5  fixupDCLJumpTargets関数

setReceiveIsochChannel関数の最後に呼んでいたfixupDCLJumpTargets関数の中身を見てみる。
    for (i = 0 ; i < isochSegments ; i++) {
        if (i != (isochSegments-1))
            (*nuDCLPool)->SetDCLBranch(receiveSegmentInfo[i].segmentEndDCL,
                                       receiveSegmentInfo[i+1].segmentStartDCL);
        else
            (*nuDCLPool)->SetDCLBranch(receiveSegmentInfo[i].segmentEndDCL,
                                       overrunDCL);
		
		// Send a notify about this dcl modification
        result = (*localIsocPort)->Notify(localIsocPort,
                                  kFWNuDCLModifyJumpNotification,
                                  (void**)&receiveSegmentInfo[i].segmentEndDCL,
                                  1) ;
        ....
コマンド列を作っていた間に設定してあったUniversalReceiveSegment構造体を取り出してジャンプ先をここで設定している。

segmentの最後になっているNuDCLコマンドの次を、次のsegmentの先頭のコマンドに設定し、最後のsegmentの最後のコマンドの次をoverrunDCLに設定している。これは標準的な順番で、コールバックの中で付け替えてover run検出をやろうと言うものだろうということがわかる。また、ローカルポートに通知を送っているが、この時点(setReceiveIsochChannel関数の最後)では必要ないはずで、このfixupDCLJumpTargets関数は実行時にコールバックから呼ばれる可能性がある、ということだろう。

この関数は最後に
    currentSegment = 0;
}
としている。currentSegmentはインスタンス変数。

3.6  startReceive関数

これは設定が終わってデータの受け取りを開始するときに呼ばれる。中身はあまり大きくなくてまず、
    pthread_mutex_lock(&transportControlMutex);
    if (transportState == kUniversalReceiverTransportRecording) {
        pthread_mutex_unlock(&transportControlMutex);
        return kIOReturnExclusiveAccess;
    }
    fixupDCLJumpTargets();
となっていて、まずtransportControlMutexミューテクスロックをロックしてtransportStateというパブリックなインスタンス変数をチェックしている。この変数はkUniversalReceiverTransportStoppedとkUniversalReceiverTransportRecordingのふたつの値をとる。要するにすでにデータ転送をしているときはなにもしない、ということで、その後念のためDCLのジャンプを整理している。

転送中でなければロックしたまま
   result = (*isochChannel)->AllocateChannel(isochChannel);
    
    if (result == kIOReturnSuccess) {
        result = (*isochChannel)->Start(isochChannel);
        if (result != kIOReturnSuccess) {
            (*isochChannel)->ReleaseChannel(isochChannel);
        }
        else {
            // Update transport state status var
            transportState = kUniversalReceiverTransportRecording;
            
            // If a registered no-data proc exists, start the timer now
            if (noDataProc)
                startNoDataTimer();
        }
    }
	
    pthread_mutex_unlock(&transportControlMutex);
として、転送を開始している。noDataProcというのは外から設定されるコールバック関数へのポインタで、startNoDataTimer関数が呼ばれてからnoDataTimeLimitInSeconds秒後にnoDataProcが呼ばれるようになっている。noDataTimeLimitInSecondsの値はコールバック関数を設定するときに一緒に設定する。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

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

トラックバック 0

献立07/13献立07/14 ブログトップ

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