0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Buffalo PC-SDVD/U2 を Raspberry Pi で動かしたかった話

Posted at

はじめに

この記事は「成功しなかった」内容です。
成功しなかった記録を残すものです。どうかこの屍を超えてください。

今回はちょっとニッチな挑戦記録です。タイトルの通り、Buffalo製のUSBビデオキャプチャデバイス「PC-SDVD/U2」を、Raspberry Pi 3で動かしてみようというお話。

え?そんなの挿せば動くでしょ?──そう思っていた時期が私にもありました...(これが言いたかっただけ)

ニッチなデバイスをを使おうとすると一筋縄ではいかぬのがLinux。

環境

  • マシン:Raspberry Pi 3 Model B
  • OS:Raspberry Pi OS Bookworm 64bit Lite(GUIなし)
  • キャプチャデバイス:Buffalo PC-SDVD/U2
    • dmesg上ではUSB 2863として認識
    • VID: 0411, PID: 015a
  • カーネル:6.12.25 → 6.12.29(手動ビルド)
  • その他ツール:v4l-utils, i2c-tools, media-ctl など

初期の動作

結論から言えば、「何も起きなかった」です。

dmesg を見ても、VID/PID は確かに表示されるものの、デバイスとしては /dev/video0 はおろか、/dev/mediaX すら出てこない。つまり、ドライバ(em28xx 系)があたっていない?

usb 1-1.3: New USB device found, idVendor=0411, idProduct=015a, bcdDevice= 1.10

この段階では、modprobe em28xxmodprobe em28xx-v4l をしても /dev/video0 は出現せず、v4l2-ctl --list-devices でも "Cannot open device /dev/video0" のエラーしか出ない。USBデバイスが接続されていても、ドライバがデバイスのVID/PIDとマッチングしない限り、何も起きないようだ。

紆余曲折ののち、ようやく /dev/media3 は現れるようにはなった。

カーネルビルド

em28xx カーネルモジュールをビルドし、VID:0411, PID:015a を持つデバイスを em28xx_id_table[] に追加していく。調べてみると、どうやら em28xx ドライバ自体はもともと存在していて、VID/PIDがテーブル上に無い為、USBが接続されても無視されているらしい。

ここからは実際の作業。

ステップ1:カーネルソースを取ってくる

sudo apt install raspberrypi-kernel-headers git bc bison flex libssl-dev make

~$ git clone --depth=1 https://github.com/raspberrypi/linux
~$ cd linux
~$ KERNEL=kernel8
~$ make bcm2711_defconfig

ステップ2:em28xxに自作デバイスを登録

drivers/media/usb/em28xx/em28xx-cards.c に、自分で定義したカード(EM2863_BOARD_CUSTOM)を追加。
これがないとVID/PIDを見てもドライバ君に「んなボードは知らん」と言われて無視されます。

ボードの定義 (drivers/media/usb/em28xx/em28xx-cards.c)

/*
 *  Board definitions
 */
const struct em28xx_board em28xx_boards[] = {
	[EM2863_BOARD_CUSTOM] = {
		.name = "Buffalo USB 2863 (custom)",
		.tuner_type = TUNER_ABSENT,
		.decoder = EM28XX_SAA711X,
		.has_msp34xx = 1,
		.has_ir_i2c = 1,
	},
	[EM2750_BOARD_UNKNOWN] = {
		.name          = "EM2710/EM2750/EM2751 webcam grabber",
		.xclk          = EM28XX_XCLK_FREQUENCY_20MHZ,

VID/PIDを自作の定義へ割り当て

/* table of devices that work with this driver */
struct usb_device_id em28xx_id_table[] = {
	{ USB_DEVICE(0x0411, 0x015a),
  			.driver_info = EM2863_BOARD_CUSTOM },
	{ USB_DEVICE(0xeb1a, 0x2750),
			.driver_info = EM2750_BOARD_UNKNOWN },

ヘッダーファイルにcard IDの登録

/* Boards supported by driver */
#define EM2863_BOARD_CUSTOM			  110
#define EM2800_BOARD_UNKNOWN			  0

この時点で decoderEM28XX_SAA711X に。
理由はあとで触れますが、「tvp5150」ではなさそうだったからです。

ステップ3:ビルドして入れる!

以下ではRaspberry Pi上でのビルドを想定したコマンドになっているが、母艦PCなどでクロスコンパイルした方が圧倒的に楽で高速なのでそっちがおすすめ。うちの環境ではwslでコンパイルしてscpで転送してました。

make -j$(nproc) Image modules dtbs # Module.symvers is missingの表示が出るので初回だけ実行
make M=drivers/media/usb/em28xx modules
sudo make M=drivers/media/usb/em28xx modules_install
sudo depmod -a

そして……新カーネルを /boot/firmware に適用

sudo cp /boot/firmware/$KERNEL.img /boot/firmware/$KERNEL-backup.img
sudo cp arch/arm64/boot/Image.gz /boot/firmware/$KERNEL.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/firmware/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/firmware/overlays/
sudo cp arch/arm64/boot/dts/overlays/README /boot/firmware/overlays/
sudo reboot

ステップ4:あらためて動作チェック (失敗)

dmesgを叩いてどういう挙動になったか見てみる

pi@RPi3:~ $ dmesg | grep em28
[    6.698677] em28xx: loading out-of-tree module taints kernel.
[    6.700503] em28xx 1-1.3:1.0: New device  USB 2863 Device @ 480 Mbps (0411:015a, interface 0, class 0)
[    6.700534] em28xx 1-1.3:1.0: Audio interface 0 found (Vendor Class)
[    6.700542] em28xx 1-1.3:1.0: Video interface 0 found: isoc
[    6.758247] em28xx 1-1.3:1.0: chip ID is em2860
[    6.880902] em28xx 1-1.3:1.0: EEPROM ID = 1a eb 67 95, EEPROM hash = 0x9a2fcb2c
[    6.880934] em28xx 1-1.3:1.0: EEPROM info:
[    6.880941] em28xx 1-1.3:1.0:        I2S audio, 5 sample rates
[    6.880948] em28xx 1-1.3:1.0:        500mA max power
[    6.880954] em28xx 1-1.3:1.0:        Table at offset 0x24, strings=0x206a, 0x0e8a, 0x0000
[    6.958092] em28xx 1-1.3:1.0: Identified as Buffalo USB 2863 (custom) (card=110)
[    6.958127] em28xx 1-1.3:1.0: analog set to isoc mode.
[    6.982407] usbcore: registered new interface driver em28xx
[    6.998213] em28xx 1-1.3:1.0: Registering V4L2 extension
[    7.125565] em28xx 1-1.3:1.0: Config register raw data: 0xf0
[    7.125595] em28xx 1-1.3:1.0: I2S Audio (5 sample rate(s))
[    7.125603] em28xx 1-1.3:1.0: No AC97 audio processor
[    7.798703] em28xx 1-1.3:1.0: failed to create media graph
[    7.798712] em28xx 1-1.3:1.0: V4L2 device vbi0 deregistered
[    7.798953] em28xx 1-1.3:1.0: V4L2 device video0 deregistered
[    7.799137] em28xx: Registered (Em28xx v4l2 Extension) extension
[    7.827879] em28xx 1-1.3:1.0: Binding audio extension
[    7.827917] em28xx 1-1.3:1.0: em28xx-audio.c: Copyright (C) 2006 Markus Rechberger
[    7.827924] em28xx 1-1.3:1.0: em28xx-audio.c: Copyright (C) 2007-2016 Mauro Carvalho Chehab
[    7.828010] em28xx 1-1.3:1.0: Endpoint 0x83 high-speed on intf 0 alt 7 interval = 8, size 196
[    7.828024] em28xx 1-1.3:1.0: Number of URBs: 1, with 64 packets and 192 size
[    7.830579] em28xx 1-1.3:1.0: Audio extension successfully initialized
[    7.830613] em28xx: Registered (Em28xx Audio Extension) extension
[    7.911779] em28xx 1-1.3:1.0: Registering input extension
[    7.911834] em28xx: Registered (Em28xx Input Extension) extension

ここで、

[    6.958092] em28xx 1-1.3:1.0: Identified as Buffalo USB 2863 (custom) (card=110)

とあることから、VID/PIDが正しく識別されてデバイスドライバが当たっていることが確認できる。

デバイスドライバの読み込み状況は

pi@RPi3:~ $ lsmod | grep em28
em28xx_rc              16384  0
em28xx_alsa            16384  0
em28xx_v4l             45056  0
em28xx                 94208  3 em28xx_rc,em28xx_alsa,em28xx_v4l
videobuf2_vmalloc      12288  2 em28xx_v4l,bcm2835_v4l2
tveeprom               20480  1 em28xx
videobuf2_v4l2         32768  5 bcm2835_codec,em28xx_v4l,bcm2835_v4l2,v4l2_mem2mem,bcm2835_isp
videodev              303104  8 bcm2835_codec,videobuf2_v4l2,em28xx_v4l,msp3400,bcm2835_v4l2,em28xx,v4l2_mem2mem,bcm2835_isp
videobuf2_common       73728  9 bcm2835_codec,videobuf2_vmalloc,videobuf2_dma_contig,videobuf2_v4l2,em28xx_v4l,bcm2835_v4l2,v4l2_mem2mem,videobuf2_memops,bcm2835_isp
mc                     61440  9 videodev,bcm2835_codec,videobuf2_v4l2,em28xx_v4l,msp3400,videobuf2_common,em28xx,v4l2_mem2mem,bcm2835_isp
snd_pcm               139264  6 em28xx_alsa,snd_bcm2835,snd_soc_hdmi_codec,snd_compress,snd_soc_core,snd_pcm_dmaengine
snd                   110592  7 em28xx_alsa,snd_bcm2835,snd_soc_hdmi_codec,snd_timer,snd_compress,snd_soc_core,snd_pcm

となり、em28周辺のドライバが自動で読み込まれていることがわかる。

v4l2-ctl上にも/dev/media3が出現するようになった。

pi@RPi3:~ $ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
        /dev/video10
        /dev/video11
        /dev/video12
        /dev/video18
        /dev/video31

bcm2835-isp (platform:bcm2835-isp):
        /dev/video13
        /dev/video14
        /dev/video15
        /dev/video16
        /dev/video20
        /dev/video21
        /dev/video22
        /dev/video23
        /dev/media0
        /dev/media1

USB 2863 Device (usb-3f980000.usb-1.3):
        /dev/media3

bcm2835-codec (vchiq:bcm2835-codec):
        /dev/media2

Cannot open device /dev/video0, exiting.

一方で、

[    7.798703] em28xx 1-1.3:1.0: failed to create media graph
[    7.798712] em28xx 1-1.3:1.0: V4L2 device vbi0 deregistered
[    7.798953] em28xx 1-1.3:1.0: V4L2 device video0 deregistered

と表示されており、media graph(こいつがなんなのかよくわからない)の構築に失敗してvideo0デバイスとしての扱いを解除されてしまっている。

またmedia-ctlでも

pi@RPi3:~ $ media-ctl -d /dev/media3 -p
Media controller API version 6.12.29

Media device information
------------------------
driver          em28xx
model           USB 2863 Device
serial          200806
bus info        usb-3f980000.usb-1.3
hw revision     0x110
driver version  6.12.29

Device topology
pi@RPi3:~ $

となっており、デバイスの基本的な情報は取得できているものの、それ以上の詳細な情報は得られていないようだ。

つまり「em28xx本体」は動いているけれど、それに接続されるべきI2Cデバイスなどとの接続が確立できていない、ということなのだろう。

i2cバス上の謎のデバイス

ChatGPTに言われるがままI2Cを探索 (i2cdetect -l) してみる。

pi@RPi3:~ $ i2cdetect -l
i2c-1   i2c             bcm2835 (i2c@7e804000)                  I2C adapter
i2c-2   i2c             bcm2835 (i2c@7e805000)                  I2C adapter
i2c-11  i2c             1-1.3:1.0                               I2C adapter

i2c-11というのがPC-SDVD/U2内部のI2Cアダプタを指しているらしい。そこで、11を指定して更にその配下の応答を探ると、

pi@RPi3:~ $ sudo i2cdetect -y 11
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- 41 -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
pi@RPi3:~ $

となる。見えているのは0x410x50の二つ。

0x50はEEPROMのアドレスで、 0x41 がどうやらsaa7113h らしい?

とりあえずsaa711x系と目星をつけて、decoderを EM28XX_SAA711X に。

dmesgにログを吐くように仕掛ける

それでも /dev/video0 は出てこない。
ならば、と em28xx のソースに pr_info() を埋め込んでみる。

	if (dev->board.decoder == EM28XX_SAA711X) {
		struct v4l2_subdev *sd;
        
		pr_info("em28xx: v4l2_init: Attempting to probe SAA711X decoder (expected addr 0x%02x or 0x%02x)...\n",
                saa711x_addrs[0], saa711x_addrs[1]);
        
		sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
                                 &dev->i2c_adap[dev->def_i2c_bus],
                                 "saa7115_auto", 0, saa711x_addrs);
        if (sd) {
            pr_info("em28xx: v4l2_init: SAA711X probed successfully at 0x%02x\n",
                    v4l2_i2c_subdev_addr(sd));
        } else {
            pr_info("em28xx: v4l2_init: SAA711X probe failed.\n");
        }
		
		// v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
		// 		    &dev->i2c_adap[dev->def_i2c_bus],
		// 		    "saa7115_auto", 0, saa711x_addrs);
	}

ログはこうなった

em28xx: v4l2_init: Attempting to probe SAA711X decoder (expected addr 0x25 or 0x24)...
em28xx: v4l2_init: SAA711X probe failed.

0x250x24 を見ているのは、I2C通信時のデバイスアドレスが7bitだかららしい。

/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
static unsigned short saa711x_addrs[] = {
	0x4a >> 1, 0x48 >> 1,   /* SAA7111, SAA7111A and SAA7113 */
	0x42 >> 1, 0x40 >> 1,   /* SAA7114, SAA7115 and SAA7118 */
	I2C_CLIENT_END };

で、0x4a >> 10x25に、0x48 >> 10x24になる。
試しに8bit→7bit変換無しでそのまま0x41を入れてみるも変化なし。
I2Cの仕様に精通していないだけに、決定的な勘違いをしている気がする。

ChatGPTもGeminiも .i2c_dev[] の再構成が必要と言うが、そんな記載は見つけられず…。カーネルバージョン差なのかハルシネーションなのかイマイチ判別も付かず。だれか助けて。


メモ

  • USBキャプチャは「認識された」だけじゃ終わらない。中の構成部品まで繋がって初めて完成
  • dmesg, media-ctl, i2cdump の三種の神器でひたすら地道に追う

おわりに

USBキャプチャをRaspberry Piで動かそうとすると、気軽に始めたつもりがいつの間にか泥沼のカーネル沼に沈んでいた──そんな体験でした。

とはいえ、今後同じようなことで悩む人にとって、この記事が「ここまでやったぞ」「ここで詰まったぞ」という道標になれば嬉しいです。

続報があれば追記します。
以上、PC-SDVD/U2との奮闘記でした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?