Raspberry PiでHDMIディスプレイを調査する[EDID/CEC]
mzyy94
mzyy94
11 min read

Categories

Tags

みなさん、テレビやディスプレイに備わるHDMIの情報を確認する必要に迫られることはありませんか? 1年に一度くらいはありますよね。映像がうまく映らなかったり、操作がうまくいかなかったり。 そんな時にパッとHDMIの情報を確認できるようになっておくべく、Raspberry PiとHDMIケーブルで調査できるようになっておきましょう。

はい、今回はRaspberry PiとHDMI EDID/CECの話。

Table of Contents

  1. HDMI
    1. EDID
    2. CEC
  2. Raspberry PiのHDMI出力
    1. HDMIの強制設定
    2. ホットプラグ対応
    3. 初期CEC無効化
    4. ブースト
  3. EDID調査
    1. EDIDのダンプ
    2. EDID解析
  4. CEC調査
    1. 接続機器の一覧
    2. テレビのスリープ
    3. デバイスのスリープ
    4. デバイスの復帰
    5. CECの監視
    6. CECフレームの送信
  5. まとめ

HDMI

HDMIには映像と音声の他に、様々な情報がやり取りされています。 イーサネット通信機能やHDMI入力端子から音声を出力して送り返す(!?)ARCなど、あげたらキリがないほど機能てんこ盛りです。

全ての機能に関する仕様書はHDMI.orgでメンバー登録してライセンス料を払うことで入手できるそうですが、ちょこっとHDMIについて知りたい場合は大袈裟すぎます。 一般人にはWikipediaでも読んで知ったつもりになるくらいで十分です。私もWikipediaで知ったつもりになりました。

HDMI - Wikipedia

このWikipediaの概要に、以下に引用した興味深い一文が掲載されています。

物理層はTMDS (Transition Minimized Differential Signaling)、信号の暗号化はHDCP (High-bandwidth Digital Content Protection)、機器間認証はEDID (Extended display identification data(英語版))、系全体の制御系接続はCEC (Consumer Electronics Control(英語版)) が採用されている。

映像と音声の伝送のほかに、機器間認証はEDIDを、制御系接続はCECを用いているとのことです。ふむふむ。

EDID

Extended Display Identification Data - Wikipedia(英語版)

表まで使って色々と詳しく説明されていますが、噛み砕いてEDIDについて説明すると、ディスプレイの機能について出力機器に伝えるためのメタデータです。 VESAの規格に従って、対応解像度や対応周波数、メーカー名やシリアルナンバーなどが記述されています。

WindowsやmacOSがディスプレイに接続して映像を出力する時、このEDIDに記述されている対応映像情報を元に、映像出力解像度やフレームレートなどが決定されています。 Raspbianも同じくして、接続されたHDMIディスプレイのEDIDを確認しています。

CEC

Consumer Electronics Control - Wikipedia(英語版)

CEC (Consumer Electronics Control) over HDMI - eLinux.org

CECはディスプレイを操作するコントローラーで、機器を制御するものです。 テレビリモコンでAmazon Fire TVを操作したり、テレビの電源に連動してゲーム機がスリープに移行する機能はCECによるものです。

昔紹介したエンターテイメントシステムのKodiもCECをサポートしています。

CEC - Official Kodi Wiki

Wikiにも紹介がありますが、Kodiが直接CECの実装を持っているのではなく、Pulse-EightのlibCECを用いてリモコンでの操作を可能としています。

Pulse-Eight/libcec: USB CEC Adapter communication Library http://libcec.pulse-eight.com/

Raspberry PiのHDMI出力

Raspberry PiのHDMI出力は、ブートローダーであり心臓部でもあるVideoCore(GPU)に直結していることもあって、レジスタ操作によってHDMIの情報にアクセスできるようになっています。

BCM2711 datasheet ARM Peripherals

ただ、画面出力目的ではなくHDMIの調査目的にHDMI出力端子を使うには、VideoCoreの設定をいくつかカスタマイズする必要があります。 設定方法は恒例の/boot/config.txtの編集です。

ドキュメントがこちらもRaspberry Pi財団によって用意されているので参照しながら設定していきます。

Video options in config.txt - Raspberry Pi Documentation

HDMIの強制設定

hdmi_drive=2

hdmi_drive

The hdmi_drive command allows you to choose between HDMI and DVI output modes.

hdmi_drive result
1 Normal DVI mode (no sound)
2 Normal HDMI mode (sound will be sent if supported and enabled)

引用元: Video options in config.txt - Raspberry Pi Documentation

HDMIはDVIと一部互換のため、DVIとして音声のない映像のみを取り扱う信号をやり取りすることもできます。 今回はHDMI信号としての情報に限って調べるため、ノイズを減らすためにHDMI信号を扱うようにしておきます。

ホットプラグ対応

hdmi_force_hotplug=1

hdmi_force_hotplug

Setting hdmi_force_hotplug to 1 pretends that the HDMI hotplug signal is asserted, so it appears that a HDMI display is attached. In other words, HDMI output mode will be used, even if no HDMI monitor is detected.

引用元: Video options in config.txt - Raspberry Pi Documentation

抜き差ししていろいろなディスプレイを調査する時や、Raspberry Piが起動してからディスプレイを接続するとき、これを有効にしておく必要があります。

初期CEC無効化

hdmi_ignore_cec_init=1

hdmi_ignore_cec_init

Setting hdmi_ignore_cec_init to 1 will stop the initial active source message being sent during bootup. This prevents a CEC-enabled TV from coming out of standby and channel-switching when you are rebooting your Raspberry Pi.

引用元: Video options in config.txt - Raspberry Pi Documentation

Raspberry PiのHDMIは、Raspberry Piの起動時にディスプレイにCECの信号を送ってスタンバイから復帰させる機能があります。 HDMI情報の調査目的でRaspberry Piを繋げて起動すると、勝手にCECの信号を送られて困るシチュエーションもあるので、そういう場合にオフにします。

ブースト

config_hdmi_boost

Configures the signal strength of the HDMI interface. The minimum value is 0 and the maximum is 11.

The default value for the original Model B and A is 2. The default value for the Model B+ and all later models is 5.

If you are seeing HDMI issues (speckling, interference) then try 7. Very long HDMI cables may need up to 11, but values this high should not be used unless absolutely necessary.

This option is ignored on the Raspberry Pi 4.

引用元: Video options in config.txt - Raspberry Pi Documentation

信号がうまく取れなかったりするときはconfig_hdmi_boostの値を変えるといいらしい。Raspberry Pi 4では動かないので効果の程はわからないです。

EDID調査

EDIDからディスプレイの情報を取得してみます。

EDIDのダンプ

Raspbianにはtvserviceコマンドが標準で用意されており、HDMI接続機器の情報を取得できます。EDIDのダンプもできます。 シンボリックリンクを経由したものがPATHに通っていますが、VideoCoreのレジスタを叩くためのコマンドであることから、/opt/vc/bin/にあります。

そしてドキュメントがRaspberry Pi財団によってWebに公開されています。(manは用意されていない。)

tvservice - Raspberry Pi Documentation

Raspberry Pi起動後に接続したディスプレイに対しては、-d(ダンプEDID)オプション以外動いてくれません。 まあ-dオプションが動いてくれれば目的のEDIDのダンプは取れるので、十分です。

tvservice help

HDMIケーブルでRaspberry Piとテレビを繋げてEDIDをダンプしてみます。対象は、1年半前に買った格安65インチ4Kテレビです。 stdoutとかには出力できないので、ファイルに出力してあげます。

pi@raspberrypi:~ $ tvservice -d /tmp/edid.bin
Written 256 bytes to /tmp/edid.bin

出力したEDIDファイルは、以下のようになっています。 これだけ見るとなんのこっちゃわかりませんね。

edid dump

EDID解析

Raspbianにはtvserviceとセットで同じ場所にedidparserコマンドがあり、これで先ほどのEDIDファイルを読める形にできます。

このパース結果から、以下のようなテレビの情報が取得できました。

  • 画面サイズ: 128x72 cm
  • 製品名: TV-monitor
  • 推奨映像モード: 3840x2160p @ 60 Hz 594 MHz
  • 対応音声フォーマット: 2 channels PCM, 32|44|48 kHz, 16 bits

CEC調査

次はCEC調査です。 先に紹介したlibCECには、クライアント実装としてcec-clientというCLIツールがセットで提供されています。 これを使ってCECの調査ができます。 libCECをビルドするか、sudo apt install cec-utilscec-clientが手に入ります。

cec-clientはログ出力がモリモリでうるさいので、-dオプションで必要なレベルまで下げます。 普段使いは-d 1です。

typedef enum cec_log_level
{
  CEC_LOG_ERROR   = 1,
  CEC_LOG_WARNING = 2,
  CEC_LOG_NOTICE  = 4,
  CEC_LOG_TRAFFIC = 8,
  CEC_LOG_DEBUG   = 16,
  CEC_LOG_ALL     = 31
} cec_log_level;

libcec/cectypes.h#L828-L836 at libcec-5.0.0

コマンドを-sオプションに続けて標準入力から与えることで、CECの調査ができます。 コマンドの一覧はecho help | cec-client -d 1 -sでわかります。

接続機器の一覧

echo "scan" | cec-client -d 1 -s

同じディスプレイに繋がっていて、CECの疎通ができるデバイスの一覧をscanコマンドで列挙できます。 認識されているデバイスを確認することができます。

list of hdmi devices

この列挙されている各デバイスの、device #の後に続く16進数がバスアドレスです。

テレビのスリープ

echo "standby 0" | cec-client -d 1 -s

テレビのバスアドレスはよっぽどのことがない限り0なので、アドレス0に向かってstandbyコマンドを叩けば、ほとんの環境でテレビをスリープできます。

デバイスのスリープ

echo "standby B" | cec-client -d 1 -s

先ほどのscanでバスアドレスBのNintendo Switchがアクティブなので、スリープさせてみます。 スリープしました。

デバイスの復帰

echo "on 4" | cec-client -d 1 -s

これも指定したバスアドレスの機器をonにできます。 Nintendo SwitchはスリープしたらCECが切断されてしまったので、AppleTVを付けてみました。付きました。

CECの監視

cec-client -m

流れているCECフレームを監視できます。 監視中にリモコンでテレビの画面を消してみました。

monitor cec of standby tv

» 0f:36 とトラフィックが流れてきているのがログに現れています。 CECのフレームは送信元4ビット、宛先4ビット、コード8ビット、それに続いて引数がつく形で表されます。 この0f:36は次のように分解できます。

  • 送信元アドレス 0 テレビ
  • 宛先アドレス f ブロードキャスト(全体)
  • コード 36 standby(スタンバイ)

libCECで扱っているコードは、cectypes.hに記載があります。

libcec/cectypes.h at libcec-5.0.0 · Pulse-Eight/libcec

CECフレームの送信

echo "tx 10:04" | cec-client -d 1 -s

データ構造がわかると、CECフレームを生で送って調査したくなりますね。 そんな時に役に立つのが、CECフレームパーサ・ジェネレーターWebアプリケーションのCEC-O-MATIC。 先ほどの監視したフレームのトラフィックもパースできます。

cec-o-matic

10:04を送ってみました。

  • 送信元アドレス 1 Raspberry Pi
  • 宛先アドレス 0 テレビ
  • コード 04 on

テレビがつきました。

まとめ

HDMIのEDIDを調査することで、ディスプレイやテレビが対応している映像モードや音声のチャンネル数などがわかります。 映像が映らない時、出力する機器が対応しているモードがないなんてことが稀にありますが、これで確認できますね。

CECの調査では、デバイスと連動してスリープにちゃんと移行しない場合など、どのようなCECフレームがやり取りされているかを確認できます。 また、どのようなフレームを送るとどういった挙動をするのか、動作確認にも使えますね。

これらのツールでみなさん良いHDMI調査ライフを〜