Haiku OSでUSBウェブカメラに挑む — XHCIドライバの深淵とISO転送の沼

みなさん、こんにちは。

前回、AI(GitHub Copilot)を相棒にして「SceneExplorer」のビルドに見事成功し、意気揚々としていた私ですが、今回はその勢いに乗って、ついに「禁断のデバイス」に手を出してしまいました。

そのデバイスとは、USBウェブカメラです。

Haiku OSのルーツは、マルチメディアに強い「メディアOS」ことBeOS。ならば、カメラ映像のストリーミングくらい朝飯前だろう……そう思っていた時期が私にもありました。しかし、そこには現代のOSが当たり前にこなしている「等時転送(Isochronous Transfers)」という名の、深く暗い沼が待ち構えていたのです。

今回は、ウェブカメラ動作に向けた奮闘記(という名の、現時点での敗北宣言)をお届けします。

SceneExplorerのビルド方法についてはこちらをご参考にどうぞ。

 


 

有志の知恵を借りて深淵へ

 

そもそも、Haiku OS にはUSBビデオクラス(UVC)デバイスを動作させるまともな標準ドライバが長らくありませんでした。

しかし、調査を進めると、有志の方がGitHubで公開されている atomozero/haiku-uvc-webcam というメディアアドオンを利用すれば動く可能性があるという情報に辿り着きました。

手元にある定番のウェブカメラ「Logicool C270n」を接続し、このアドオンをビルドして media_server に認識させれば、標準アプリの「CodyCam」でサクッと映像が出るはず。そう信じて疑わなかったのですが、ここからエンジニアとしての意地をかけ、GitHub CopilotとともにOSカーネル層にまで及ぶデバッグの日々が始まりました。

 


 

第一の壁 – XHCIドライバの「リングバッファ溢れ」

 

USBウェブカメラは、映像データを一定間隔で流し続ける「等時転送(ISO)」を使用します。

ここでHaikuのUSB 3.0ドライバ(xhci.cpp)のソースコードを覗いてみると、驚くべき事実が判明しました。

等時転送用のリングバッファサイズ XHCI_ENDPOINT_RING_SIZE が、わずか 16スロット しか用意されていなかったのです。

対して、利用した haiku-uvc-webcamUVCCamDevice.cpp は、一度に 32パケット をキューに積もうとしていました。1パケットあたり3つのTRB(Transfer Request Block)を消費するため、合計エントリ数は 96

96 > 16

完全にキャパシティオーバーです。ログには何百万行もの ISO FAIL が流れ、転送エラーの嵐。

GitHub Copilotの力を借り、一度に送る kInitialPackets を 4 に減らし、12エントリに抑えることで、ひとまずバッファ溢れは解消しました。

 


 

第二の壁 – 帯域幅確保の失敗(Alt 7の拒絶)

 

バッファ問題を解決しても、まだ映像は出ません。

C270nは「高帯域幅エンドポイント(Alt 7)」を使おうとします。これは1マイクロフレームあたり最大3060バイトを転送する設定ですが、HaikuのXHCIドライバはこの帯域幅確保ロジックに不具合があり、「Bandwidth error」で接続を拒否してしまいます。

こればかりはアドオン側ではどうにもなりません。仕方なく、カーネルの xhci.cpp に直接パッチを当て、無理やりこのエラーを回避するバイナリを配置するという、かなり強引な手法で突破しました。

 


 

第三の壁 – デバッグパッチが生んだ「波括弧なしif文」の罠

 

ようやく接続が通るようになったものの、今度は WaitFrame TIMEOUT が延々と続き、ハングしてしまいます。ここでCopilotにデバッグコードを挿入してもらった際、思いもよらない「トラップ」に嵌まりました。

C++の「波括弧 { } なしのif文」に対して、スクリプト(awk)でデバッグ用のログ挿入パッチを当てた結果、以下のような構造になってしまったのです。

// 意図した動作
if (!lock.IsLocked())
    break;

// パッチ後のバグ(syslogがifの本体になり、breakが外に漏れた)
if (!lock.IsLocked())
    syslog(...); 
break; // 無条件でループを抜けてしまう!

このせいでデータ転送ループが常に1回で終了していました。まさに「デバッグコードがバグを生む」という、エンジニアが一番頭を抱えるパターンです。バックアップから復元して事なきを得ましたが、「AIの作業は完璧ではない。特にコンテキストの深い構文解析には人間の目が必要だ」という教訓を改めて思い知らされました。

 


 

第四の壁 – TBC=0問題(最後の守護神)

 

バグを修正しても、やはり映像は出ません。原因の核心は、XHCIのTRBにおける TBC(Transfer Burst Count)フィールド にありました。

Haikuのドライバでは、この値が「0」にハードコードされています。

Alt 7のような高帯域エンドポイントは、1マイクロフレームで複数のトランザクションを要求しますが、TBC=0はコントローラに「1回で十分」と伝えてしまいます。その結果、転送処理が永久にブロック(ハング)してしまうのです。

万策尽き、高帯域モードを諦め、1トランザクションで動作する「Alt 3(1024バイト/マイクロフレーム)」を強制的に使うようアドオン側のコードを修正しました。

 


 

現状 – 沼の深淵にて

 

ここまで4層の壁を突破し、ようやくISOループが回り始めたのですが……現状、私は以下の状況で立ち往生しています。

  • Alt 3への強制切り替えパッチは適用済み。
  • しかし、media_server が再起動を繰り返すサイクルに陥り、タイムソース取得エラーが発生。
  • どうやら、カーネルのさらに深い部分に致命的なエラーが残っている模様。

正直に言いましょう。私はここで力尽きました(泣)。

 


 

楽しむために待つ

 

単純なウェブカメラ接続だと思って手を出しましたが、蓋を開けてみれば「XHCIドライバの設計制限」「帯域幅確保のバグ」「C++の構文トラップ」「ハードコードされたTBC」という、まさに地獄の四連コンボでした。

有志の方が作成されたアドオンという素晴らしい素材があっても、それを受け止めるOS側のドライバ層、特にUSBの等時転送のような「リアルタイム性が命」の領域は、Haikuにおいてまだまだフロンティアであることを痛感しました。どんなにAIの力が優れていても、土台が脆ければ、その上には何も築けません。

私はIoTエンジニアとして多くのデバイスを扱ってきましたが、OSのカーネル開発者ではありません。これ以上の深追いは、本来の「Haikuを楽しむ」という目的を失いかねません。

残念ですが、この先の戦いは、Haiku OSチームの精鋭たちがUSBスタックを抜本的に改善してくれるのを、気長に待つことにしましょう。

 

本日も最後までお読みいただきありがとうございました。

それでは、よい(そして平穏な)Haiku OSライフを!

カテゴリ: Tips, 開発インフラ

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール