NuDCLその10 [Mac用USBデバイス工作]
FireWireのアイソクロナス転送でデータをやりとりするためのMacOS XのI/O KitによるメカニズムであるDCLを使ったAppleのサンプルコードのアイソクロナス転送をするC++クラスであるUniversalReceiverのメンバ関数の中身を見ている。今日はその続き。
segmentの最後になっているNuDCLコマンドの次を、次のsegmentの先頭のコマンドに設定し、最後のsegmentの最後のコマンドの次をoverrunDCLに設定している。これは標準的な順番で、コールバックの中で付け替えてover run検出をやろうと言うものだろうということがわかる。また、ローカルポートに通知を送っているが、この時点(setReceiveIsochChannel関数の最後)では必要ないはずで、このfixupDCLJumpTargets関数は実行時にコールバックから呼ばれる可能性がある、ということだろう。
この関数は最後に
転送中でなければロックしたまま
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の値はコールバック関数を設定するときに一緒に設定する。
2010-07-13 22:05
nice!(0)
コメント(0)
トラックバック(0)
コメント 0