メインコンテンツまでスキップ

デバイスタイプの追加

Sentinelの周辺機器カタログはハードウェアの事実を一覧表示します。 新しい種類のデバイス(たとえばディスプレイやシリアルアダプター)には、型付きのレコード、それを検出するプロバイダー、 テスト、およびこのディレクトリ内のページが必要です。 アプリケーションがデバイスをサポートするかどうかは、Sentinelではなく、そのアプリケーションが判断します。

1. レコードを定義する​

src/peripherals/の下に、デバイス用のserde構造体を持つモジュールを追加し、 それをsrc/peripherals/mod.rsのPeripheralのバリアントとして追加します。 バリアント名はJSONのtypeタグになるため、Display(display::Display)は {"type": "display", ...}としてシリアライズされます。Peripheral::id、kind、describeを 新しいバリアントに合わせて拡張してください。

  • idは再接続や再起動をまたいで安定している必要があります。バスパス、 シリアル番号、またはそれらを経ても変わらない別の属性から導出し、 カード番号や/dev/videoNのような列挙インデックスからは決して導出しないでください。
  • idはカタログ全体で一意である必要もあります。ワーカーは これをチェックしません。既存のid(camera:v4l2:…、microphone:alsa:…)と同様にタイプとプロバイダーを接頭辞として付け、 残りの部分は、接続先のポートなど、 同一の2台のデバイスが共有できないものから構成してください。 シリアル番号だけでは不十分です。安価なデバイスでは同じ番号が繰り返されることがよくあります。
  • 省略可能な事実はOptionフィールドとし、 既存のレコードと同様に#[serde(default, skip_serializing_if = "Option::is_none")]を付けます。 これにより、不明な事実はJSONから省かれます。単なる Optionではnullとしてシリアライズされてしまいます。
  • カーネルやデバイスが公開する事実を報告してください。 モードがサポートされているかどうかなど、ポリシーを表すフィールドは追加しないでください。

2. プロバイダーを実装する​

Providerトレイトを実装します:

pub trait Provider: Send {
fn name(&self) -> &'static str; // e.g. "display.drm"
fn subsystems(&self) -> &'static [&'static str]; // uevent subsystems, e.g. ["drm"]
fn discover(&mut self) -> Result<Vec<Peripheral>, ProviderError>;
}

discoverは、peripheralsスレッド上で1回の完全なスキャンを実行します。 ワーカーは起動時、subsystemsのいずれかからのuevent受信後、およびリフレッシュ時にこれを呼び出します。

  • 読み取り専用。 デバイスノードは読み取り専用で開き、照会インターフェースのみを使用してください。 デバイスを取得、設定したり、デバイスからストリーミングしたりしないでください。
  • 上限を設ける。 読み取るすべてのリストとすべての照会ループに上限を設け、 壊れたデバイスがスキャンを停滞させないようにしてください。 videodev2.rsのV4L2ヘルパーがそのパターンを示しています。
  • エラー。 スキャンを完了できない場合は、ProviderErrorを返します。コードにはio.permission_denied やio.openなどを使用します(sysutil.rsを参照)。その後、カタログは このプロバイダーの最後の正常なデバイスを保持し、エラーをerrorsに記載します。 スキャン中に消えたデバイスはエラーではなくスキップされます。その取り外しによって送信される ueventが再スキャンをトリガーします。
  • 失敗させずに縮退する。 省略可能な属性が欠けている場合は、そのフィールドを省きます。 存在するが読み取れない属性は、その用途に応じて扱います:
    • デバイスの検出や識別にスキャンが必要とする属性(idやUSBの 識別情報)はエラーとし、プロバイダーの最後の正常なデバイスが保持されるようにします。
    • 事実を追加するだけの属性の場合は、その事実を除いたうえでデバイスを公開し、 レコードに理由を記録します(マイクのレコードのissuesは、 読み取れないキャプチャメタデータに対してこれを行っています)。

プロバイダーをsrc/peripherals/mod.rsのbuiltin_providers()に登録します。

3. テストする​

テストはライブシステムではなくフィクスチャツリーを読み取ります。 プロバイダーにsysfs、procfs、/devのルートをパラメーターとして渡し、 alsa/tests.rsやv4l2/tests.rsのようにioctlレイヤーを偽装します。 手元のデバイスだけでなく、そのクラスのデバイスが異なり得るあらゆる点をカバーしてください: 数、フォーマット、範囲と離散値、欠落した省略可能フィールド、同時に存在する複数の同一デバイス、 スキャン中に消えるデバイスなど。 同一の2台のデバイスに異なるidが付くことをアサートしてください。 実際のハードウェアからコピーしたフィクスチャには、実キャプチャであることを示すラベルを付けてください。

cargo test --lockedが成功し、cargo fmt --checkとcargo clippy --locked --all-targetsが新たな問題を報告しないことが必要です。

4. ドキュメントを作成する​

このディレクトリに、プロバイダー名、ueventサブシステム、idの導出方法、 各フィールドとその出現条件、エラーコード、およびJSONの例を記載したページを追加します。 そのページをAPIリファレンスと ドキュメントインデックスからリンクし、翻訳を再生成してください (ローカライズを参照)。