HDMI-CEC

提供: ArchWiki
ナビゲーションに移動 検索に移動

High-Definition Multimedia Interface - Consumer Electronics Control は、HDMI 接続内の追加の低速(50 B/s)バスであり、HDMI デバイスの「ネットワーク」が互いに通信するために使用できます。これにより、HDMI デバイスはお互いにオンまたはオフにすることを通知したり、テレビが入力を切り替えたり、リモコンのボタンが押されたりするなどの操作が可能になります。PC セットアップでは、通常、HTPC(ホームシアターPC)セットアップで遭遇します。

様々な理由から、ほとんどの PC GPU は CEC のハードウェアサポートを持っていません。ビデオゲームコンソールやセットトップボックスは通常、CEC ピンを駆動するために外部チップセットを含める必要があります。Raspberry Pi で見られる VideoCore GPU のようにネイティブ CEC サポートを持つデバイスもありますが、ほとんどのハードウェア構成では追加のハードウェアが必要です。

機能

CEC (Consumer Electronics Control) の主な目的は、テレビがそれに接続されているデバイスの状態を把握し、制御することを可能にすることです。そのため、特定の使用例に対応する "機能" のいくつかに分けられており、デバイスは発信者/フォロワーとしての役割、能力、ユーザー設定に基づいて、これらの機能をサポートするかどうかを選択できます。

標準化された機能は以下の通りです:

ワンタッチプレイ
デバイスが直ちにアクティブソースになることを希望していることを示し、自動的にテレビをオンにすることができます
ルーティング制御
テレビが HDMI スイッチを制御できるようにし、デバイスが現在アクティブなソースを確認できるようにします
リモートコントロールパススルー
デバイスが互いにリモコン信号を送信できるようにします。通常はテレビからアクティブソースへ送信されます
デッキコントロール
映画/音楽プレイヤーを制御し、その再生状態を照会する
スタンバイ/システムスタンバイ
デバイスが別の特定のデバイスの電源を切ることを要求したり、システム上のすべてのデバイスが今電源を切るべきだと放送することができます
電源状態
デバイスがスタンバイモードにあるか、オンになっているか、またはオンになるプロセス中にあるかを調べることができます
システムオーディオコントロール
テレビのオーディオリターンチャネルを介して接続された AV レシーバーを制御できるようにし、音量を変更したりレシーバーの電源を入れたり切ったりできます
チューナーコントロール
任意のデバイスがチューナーデバイスに知られているテレビチャンネルのリストを通過し、アクティブなチャンネルの情報 (アナログテレビのチャンネル番号やデジタルテレビの DVB/ATSC/ARIB トランスポートストリーム情報など) を照会できます
ワンタッチレコード
レコーダーがテレビが現在表示しているチャンネルを照会できるようにし、そのレコーダーが同じチャンネルにチューニングして録画を開始するか、既に現在アクティブな HDMI ソースであれば自身や下流デバイスを録画すべきかを知ることができます
タイマープログラミング
テレビが特定の時間に特定のソースの録画を開始するためにレコーダー上のタイマーを設定できるようにします
OSD表示
デバイスがテレビ上にメッセージを表示できるようにします。1 から 13 文字の ASCII 文字で
ダイナミックオートリップシンク
テレビがオーディオシンクへのプレゼンテーション遅延の変更を放送できるようにします。これは、独自のスピーカーを持つソース (PC など) が画像との遅延補償に使用できます。
ヒント: リストにないもの:デバイスメニューコントロール (CEC 2.0で廃止)、OSD 名転送 (cec-ctl によって処理)、システム情報、ベンダー固有のコマンド (標準化されたメッセージなし)、オーディオレートコントロール (TV-AV のみ)、オーディオリターンチャネルコントロール (TV-AV のみ)

PC のようなデバイスにとって、これらの中で最も有用なのは リモートコントロールパススルー でしょう。HTPC にとっては システムスタンバイ が有用かもしれませんが、スクリーンがオフになったときに通常スリープ状態に入ることが期待されないより一般的な用途のマシンでは疑問の余地があります。ルーティングコントロール は、テレビがその入力を表示しようとするときにシステムを起動させるために使用できますが、接続されたPCがサスペンド中にCECトラフィックを待ち受ける方法を持っている場合に限ります。システムオーディオコントロール は、一部の HDMI サウンド出力にとって便利ですが、現在、PipeWirePulseAudio といったもので音量制御の手段としては機能していません。

ハードウェアセットアップ

Linux のカーネルには既に CEC イベントに自動的に応答し、処理するための組み込みのサブシステムがありますが、ハードウェアが正しく機能するためには最初に設定が必要になる場合があります。

Native CEC

Native CEC は主に ARM デバイスで見られます。x86 世界では、DisplayPort経由のトンネリングが最も簡単なオプションです。それ以外では、一部の Chrome OS デバイスと SECO UDOO のシングルボードコンピューターのみが CEC を提供しています。

DisplayPort 経由のトンネリング

これは i915nouveauamdgpu ドライバーで機能します。2014 年に導入された DisplayPort 1.3 標準では、DisplayPort から HDMI アダプターを使用して補助チャネルを介して CEC 信号を双方向に転送することができます。これはアダプターが通常サポートしていない種類の機能であり、一般的ではありませんが、USB-CEC アダプターよりも直感に反して CEC のトンネリングを DisplayPort 経由で使用する方が安価で簡単な場合があります。CEC サブモジュールのカーネルドキュメントページには、動作が確認されたアダプターのリストがあります。

CEC アダプター

ノート: Kodi で HDMI-CEC を使用しようとしている場合、それは Pulse-Eight および Raspberry Pi の CEC 制御モードの両方の組み込みサポートを持っており、以下の設定と互換性がありません。

PulseEight USB アダプター

PulseEight USB-CEC アダプターは、"PC 側" コネクタから "TV 側" コネクタへ HDMI コネクタのすべてのピンを受動的に延長しますが、CEC ピンを除きます。そのピンを通るデータは、PC が CEC トラフィックを制御し監視できるように USB シリアルインターフェース上で公開されます。シリアルデバイス は、カーネルがそれを CEC アダプターとして認識し、引き継ぐ前に手動でそのラインディスプリン(TTY が特定の既知のタイプであり、動作にドライバーが必要であることをカーネルに信号を送るフラグ)を設定する必要があります。シリアルデバイス API の制限のためにこれを自動的に行うことはできないため、現在はデバイスが接続されたときに inputattach --pulse8-cec ... を実行する udev ルールsystemd ユニット(udev ルールでは長時間実行またはフォークするプロセスを起動できないため) を組み合わせて実現するのが最善の方法です。

このシリアルインターフェースはデバイスノード /dev/ttyACMX として現れ、後で必要となる /dev/cecX デバイスを作成するために、inputattach ユーティリティを使ってラインディシプリンを設定し、カーネルドライバーに処理を引き継がせる必要があります。これには linuxconsole パッケージが必要です。

ノート: 以下のルールで @$devnode を変更しないでください。これは udev の文字列置換です。
/etc/udev/rules.d/pulse8-cec-autoattach.rules
SUBSYSTEM=="tty" ACTION=="add" ATTRS{manufacturer}=="Pulse-Eight" ATTRS{product}=="CEC Adapter" TAG+="systemd" ENV{SYSTEMD_WANTS}="pulse8-cec-attach@$devnode.service"
/etc/systemd/system/pulse8-cec-attach@.service
[Unit]
# Should be called as "pulse8-cec-attach@-dev-ttyACM0.service" or similar
Description=Configure USB Pulse-Eight serial device at %I
ConditionPathExists=%I

[Service]
Type=forking
# inputattach is built without systemd daemon support by default, so systemd will have to guess the PID.
# https://sourceforge.net/p/linuxconsole/code/ci/a3366c0d5f82485e6aae7b005ec7a2d9a93bf458/tree/utils/inputattach.c#l1233

ExecStart=/usr/bin/inputattach --daemon --pulse8-cec %I

しかし、USB デバイス接続は、システムがスリープから復帰するときに通常リセットされます(これは "reset-resume" として知られています) これは、コンピュータがサスペンドされた場合、シリアル接続が失われることを意味します。さらに、通常、シリアル接続は復帰時に切断されがちです。このため、上記のルールを何らかの方法で再度トリガーする必要があります。

残念ながら、上記のルールが反応する ttyACM* オブジェクトを担当するcdc_acmドライバは、接続がリセットされてラインディスプリンが失われたことについての uevent を発生させず、USB デバイス直接にルールをフックすることはできません。代わりに、正しいタイミングで上記の使用されたルールを再度トリガーする最も確実な方法は、リセット時に USB デバイスを再設定することを強制して ttyACM* オブジェクトを削除して再作成することです。これにより、udev は USB デバイスがリセットされて列挙されるときを追跡でき、DEVNUM プロパティがゼロになり後で復元されること、bConfigurationValue sysfs 属性を触ることにより、接続が再開されることを確実にします。

/etc/udev/rules.d/pulse8-cec-autoattach.rules
SUBSYSTEM=="tty" ACTION=="add" ATTRS{manufacturer}=="Pulse-Eight" ATTRS{product}=="CEC Adapter" TAG+="systemd" ENV{SYSTEMD_WANTS}="pulse8-cec-attach@$devnode.service"

# Force device to be reconfigured when reset after suspend, otherwise the ttyACM link is lost but udev will not notice.
# A usb_dev_uevent with DEVNUM=000 is a sign that the device is being reset before enumeration.
# Re-configuring causes ttyACM to be removed and re-added instead.
SUBSYSTEM=="usb" ACTION=="change" ATTR{manufacturer}=="Pulse-Eight" ATTR{product}=="CEC Adapter" ENV{DEVNUM}=="000" ATTR{bConfigurationValue}=="1" ATTR{bConfigurationValue}="1"

これは基本的に、USB アダプタがスリープから出た直後に抜き差しされたかのように機能し、以前の SUBSYSTEM=="tty" ACTION=="add" ルールが再び実行されることを保証します。これにより、デバイスが使用可能な状態に戻るとすぐに systemd サービスが再起動されることが保証されます。

ソフトウェアセットアップ

CEC サブシステムがバインドするものを持つようになり、/dev/cec0 が作成されたので、他の CEC デバイスが PC を認識するように設定することが可能になりました。コマンドラインを使用する場合、CEC デバイスは通常、v4l-utils の一部である cec-ctl を介して制御されます。

USB アダプターに物理アドレスを通知する

注意すべきことの 1 つは、CEC ピンだけでは有効な CEC メッセージを送信するのに十分な情報がないことです。ピン 13 (CEC) のみを監視する CEC アダプターは、自身の "物理アドレス" を知ることができません。これは、ポート番号の観点から HDMI デバイスの "ツリー" における位置を表す 16 ビットの値です。

ノート:

テレビは HDMI ルートであり、常にアドレス 0.0.0.0 を持ちます。テレビのポート HDMI2 に直接接続されたデバイスは、アドレス 2.0.0.0 を持ちます。テレビの HDMI3 ポートに接続されている AV レシーバーのポート 6 に接続されたデバイスは、3.6.0.0 となります。

アダプターは、次のセクションで詳述する "論理アドレス" 割り当て手順を完了するために、この物理アドレスを認識する必要があります。物理アドレスはピン 16 (DDC/EDID) を介して通信されるため、CEC サブシステムの設定には、物理アドレスがディスプレイの EDID から抽出されるように、どのディスプレイ出力ポートをその CEC オブジェクトに関連付けるかを指定することが含まれます。

アクティブなコネクタの名前を見つける方法の 1 つは、xrandr --query を使用することです (Wayland でも機能します)

$ xrandr --query 
Screen 0: minimum 16 x 16, current 3840 x 2160, maximum 32767 x 32767
DP-1 connected primary 3840x2160+0+0 (normal left inverted right x axis y axis) 600mm x 340mm
   3840x2160     59.98+
   2048x1536     59.95  
   ...
HDMI-A-1 connected 3840x2160+0+0 (normal left inverted right x axis y axis) 1440mm x 810mm
   3840x2160     59.98+
   2048x1536     59.95  
   ...

正しいポート (たとえば HDMI-A-1) が識別されたら、ls -1d /sys/class/drm/card*-HDMI-A-1 (たとえば card1-HDMI-A-1) を使用して sysfs ポート名を見つけることができます。この場合、対応するディスプレイの EDID データは /sys/class/drm/card1-HDMI-A-1/edid に保持されます。

物理アドレスは次のようにプレビューできます。

$ edid-decode --physical-address /sys/class/drm/card1-DP-3/edid
4.0.0.0

CEC 設定は cec デバイスノードが再作成されるたびに実行する必要があるため、これは cec オブジェクトが表示されたときに起動する別の udev ルールで処理するのが最適です。

ノート: 次のルールで card1-HDMI-A-1 をコネクタ名に置き換えてください。
/etc/udev/rules.d/cec-configure-autostart.rules
SUBSYSTEM=="cec" KERNEL=="cec0" ACTION=="add" TAG+="systemd" ENV{SYSTEMD_WANTS}="cec0-configure@card1-HDMI-A-1.service"
/etc/systemd/system/cec0-configure@.service
[Unit]
Should be called as "cec0-configure@card1-HDMI-A-1.service" or similar

Description=Configure CEC adapter cec0 assuming it runs on output %i
AssertPathExists=/sys/class/drm/%i/edid
BindsTo=dev-cec0.device

[Service]  
Type=exec
--phys-addr-from-edid-poll checks EDID every tenth of a second
https://git.linuxtv.org/v4l-utils.git/tree/utils/cec-ctl/cec-ctl.cpp?id=0a195181d771090f3c99d4a6ddb8151352509061#n1977
Use Type=oneshot if using --phys-addr-from-edid instead

ExecStart=/usr/bin/cec-ctl --device=0 "--osd-name=%H" --playback "--phys-addr-from-edid-poll=/sys/class/drm/%i/edid"

詳細については、次のセクションを参照してください。

論理アドレスの取得

帯域幅が非常に限られているため、CEC プロトコルでは 16 ビットの物理アドレスの代わりに、より短い 4 ビットの論理アドレスを使用して、各メッセージの送信元と宛先をマークします。論理アドレスがない場合、デバイスはブロードキャストメッセージのみを受信および送信できます。これにより、デバイスは "チューナー #3" または "再生デバイス #1" として識別され、それぞれの数が有限になります。これらの役割は、前述の CEC 機能 に関連することを意図しています。

チューナー (最大 4 つ)
"チューナー制御" 機能をサポートする必要があります。
レコーダー (最大 2 つ)
"ワンタッチ録画" を使用できる唯一のタイプ。テレビは他のアドレスから来る関連メッセージを無視することになっています。
再生デバイス (最大 3 つ)
汎用ビデオソース。コンピューターとビデオゲームコンソールは "再生デバイス" と見なされます。
バックアップ (最大 2 つ)
あるタイプのデバイスが多すぎるためにアドレス割り当てが失敗した場合に使用できます。

残りの 4 つのアドレスは、テレビ自体、オーディオシステム、あいまいな "特定用途デバイス" (おそらく 2 番目のテレビ)、およびデフォルトのブロードキャスト/未登録アドレス用に予約されています。HDMI スイッチは "透過的" であり、独自のアドレスを持ちません。

前回とは異なり、cec-ctl への必要な呼び出しは、udev ルールの一部として直接機能するのに十分なほど短時間で済みます。以前に物理アドレス設定用の systemd ユニットを作成している場合は、このルールは冗長であり、無視できます。

/etc/udev/rules.d/cec-configure-autostart.rules
SUBSYSTEM=="cec" KERNEL=="cec0" ACTION=="add" RUN+="/usr/bin/cec-ctl '--device=$devpath' '--osd-name=14_CHARS_MAX' --playback"

上記の udev ルール (および以前の systemd ユニット) は、--playback を使用して再生デバイスを設定します。ただし、未使用の再生アドレスがなくなったため、または単にテレビの入力メニューで各デバイスクラスを視覚的に区別するテレビのリストで PC を目立たせるために、デバイスクラスをチューナー (--tuner) またはレコーダー (--record) に設定しても一般的には問題ありません。このルールでは、--osd-name=14_CHARS_MAX を使用して、テレビメニューで使用されるアドバタイズされたソース名を設定します。例示の名前が示すように、これは 14 文字の ASCII 文字のみに制限されています。

入力処理デーモン

ユーザー空間ツール

/dev/cec* デバイスへのユーザーアクセスは、ユーザーを video ユーザーグループに登録することで許可されます。CEC デバイスを制御する基本ツールは v4l-utils からの cec-ctl です。同様のものに libcec からの cec-client があり、python-cecAUR で利用可能な Python バインディングもあります。

CEC の用途

リモートコントロールパススルー

cec0 オブジェクトが設定されると、Linux CEC サブシステムは /sys/class/rc に一致するオブジェクトも作成します。これは、UI コマンドコード信号を同等のキープレスに変換する 入力デバイスとして機能します。

  • 通常はリモコン自体にはない「Power」信号は、メニューから送信できます。KDE ではデフォルトで "セッションを閉じる" 確認画面が表示され、GNOME ではキーボードのサスペンドボタンと同様にシステムがすぐにサスペンドされます。
    • 起動については、#Wake-on-CEC を参照してください。
  • 矢印ボタンは矢印ナビゲーションキーにマッピングされ、どこでも機能します。
  • "戻る" および "選択" ナビゲーションボタンは、"Escape" キーと "Enter" キーではなく、"OK" および "EXIT" メディアボタンにマッピングされます。これらは一部のメディアプレーヤーでのみ認識されます。
  • "再生"、"一時停止"、および "停止" はメディアキーと同じように機能し、DE の構成によっては、プレーヤーがフォーカスされていなくても、どこでも認識されます。
    • "巻き戻し"、"早送り"、"次のトラック"、および "前のトラック" は通常無視されますが、VLC と Totem はそれらを認識します。
  • 数字ボタンクラスターの "ドット" は、テンキーの "." キーとして認識されます。
  • "メニュー"、"設定"、"オーディオ"、および「録画」などの他のさまざまなキーは、デフォルトでは何もしませんが、ほとんどのアプリケーションで有効なキーボードショートカットとして割り当てることができます。
  • 4 つの色付きのファンクションボタン、数字ボタン、およびチャンネル +/- ボタンなどは、アプリケーションによってキーボードまたはメディアキーとして認識されませんが、それらが生成する evdev キーイベントは、それらを明示的にチェックするアプリケーションで使用できます。
  • 音量コントロールは通常、ソースに渡される代わりにテレビによって傍受されますが、パススルーされる場合は通常の音量キーとして処理されます。

Wake-on-CEC

HDMI デバイスは通常、ルーティングコントロール機能を使用して、テレビがアクティブなソースになるとテレビから通知されます。これは、サスペンドされたデバイスをウェイクアップするために使用できますが、コンピューターの場合には問題が発生します。CEC サポートは Linux カーネルまたはユーザー空間ライブラリを介して実現され、マザーボード自体によって処理されないため、コンピューターがサスペンドされている間は CEC トラフィックを待ち受けるものがありません。

DisplayPort-HDMI アダプターと比較した Pulse-Eight アダプターの利点の 1 つは、ホストシステムがスタンバイ状態でも電源がオンのままでアクティブにできることです。物理アドレスと論理アドレスが通知されると、USB ホストがなくなったことを検出した場合、電源がオンのままである限り "自律モード" で動作し続けます。この状態の間、次の処理を継続します。

  • システム情報照会 (オンスクリーン名、論理アドレス、現在の電源状態など) に応答する。
  • "Power" リモート信号または <Set Stream Path> メッセージ (宛先が自身である) に、PC に電源スイッチイベントを送信してウェイクアップすることで応答します。

Pulse-Eight USB アダプターは、シリアルインターフェースとともに USB キーボードとして登録されるため、これを行うことができます。DisplayPost-HDMI アダプター (DisplayPort オルタネートモードを使用する USB-C アダプターを含む) には、この種のサイドチャネルがないため、このようにホストをウェイクアップできません。

Raspberry Pi のようなネイティブ CEC サポートを備えたデバイスには、通常、サスペンドモードはありません。Pi 自体は電源を切ることができますが、この状態では CEC ピンを待ち受けせず、この方法で電源を入れるには外部回路が必要 です。

CEC トラフィックの監視

CEC をサポートするデバイスでできる興味深いことの 1 つは、CEC ラインをタップして他のデバイスが何を言っているかを確認することです。CEC ラインは、CEC をサポートしていないデバイスも含め、すべてのデバイス間で "物理的に" 相互接続されているため、どのデバイスから送信されたメッセージも、位置に関係なく、他のすべてのデバイスから見ることができます。cec-ctl でこれらのメッセージをログに記録するには、次のコマンドを実行するだけです。

# cec-ctl -d0 --monitor-all --ignore=all,poll

通常、除外できる特定のメッセージの 1 つはポーリングメッセージです。論理アドレス割り当て手順では、これらのアドレスを解放する手段は定義されていないため、アドレスが利用可能になったかどうかを確認する予期される方法は、ping と同様に、送信元アドレスと宛先アドレスを含むメッセージを送信することで定期的にポーリングすることです。メッセージが確認応答されない場合、この論理アドレスのデバイスは "不要/使用しなくなった" と理解され、存在しないと見なされます。したがって、ほとんどのテレビは、ダウンストリームデバイスの状態を確認するために、これらのデバイスを非常に頻繁にポーリングします。--ignore=all,poll (すべてのポーリングメッセージを送信元に関係なく無視する) または --ignore=0,poll (テレビからのポーリングメッセージのみを無視する) を使用すると、ログのノイズを減らすことができます。

参照