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?

DVB版ドライバで動くチューナが複数ある場合にマウントポイントを固定させる方法

Last updated at Posted at 2025-10-05

概要

PT3などのチューナデバイスのLinux版ドライバには、独自のAPIで実装されたchardev版のドライバと、LinuxTVのインターフェイスに準拠したDVB版があります。DVB版ドライバで動くデバイスが複数存在する場合、起動時に/dev/dvb/adapter0などにマウントポイントが作成されます。が、この数字は単純にドライバが読み込まれた順番みたいで、うまく制御する方法が見つからなかった(udevルールなども調べたがチューナ情報によってシンボリックリンクを貼る場所を変える処理ができず断念)ので、どうにかして固定しようというのが目的です。

Pythonスクリプトを書く

とりあえず/dev/dvb/adapter0とかに自動で生える部分はうまく制御できなそうだったので、起動後に次のようなPythonスクリプトを実行し、シンボリックリンクを貼ることにします。

方針としては、DVBデバイスに対してioctl経由で、FE_GET_INFOというコマンドを実行します。詳細については公式ドキュメントにかいてあります。ここからGETすると、dvb_frontend_infoという構造体が帰ってきます。この構造体の中に、nameというフィールドがあり、ここを見るとどのチューナかわかるという仕組みです。今回の場合は、PT4KとPT3の区別をしたいので、「Turbosight TBS 6812 (Dual ISDB-T/S/S3)」の場合は/dev/pt4k/adapter{k}に、「Toshiba TC90522 ISDB-S module」の場合(PT3の場合)は、/dev/pt3/adapterS{k}に…というように処理しています。ISDBScannerの処理と同じです。

import ctypes
import glob
import fcntl

FE_GET_INFO = 0x80A86F3D


class DvbFrontendInfo(ctypes.Structure):
    _fields_ = [
        ("name", ctypes.c_char * 128),
        ("type", ctypes.c_uint),
        ("frequency_min", ctypes.c_uint32),
        ("frequency_max", ctypes.c_uint32),
        ("frequency_stepsize", ctypes.c_uint32),
        ("frequency_tolerance", ctypes.c_uint32),
        ("symbol_rate_min", ctypes.c_uint32),
        ("symbol_rate_max", ctypes.c_uint32),
        ("symbol_rate_tolerance", ctypes.c_uint32),
        ("notifier_delay", ctypes.c_uint32),
        ("caps", ctypes.c_uint),
    ]


def synbolic_link_rule(path: str) -> str:
    if path == "Turbosight TBS 6812 (Dual ISDB-T/S/S3)":
        return "/dev/pt4k/adapter{k}"
    elif path == "Toshiba TC90522 ISDB-S module":
        return "/dev/pt3/adapterS{k}"
    elif path == "Toshiba TC90522 ISDB-T module":
        return "/dev/pt3/adapterT{k}"
    return None


devices = glob.glob("/dev/dvb/adapter*/frontend*")
count_dict = {}

for device in devices:
    with open(device, "rb", buffering=0) as f:
        fe_info = DvbFrontendInfo()
        fcntl.ioctl(f, FE_GET_INFO, fe_info)
        name = fe_info.name.decode()
        path = synbolic_link_rule(name)

        if path in count_dict:
            count_dict[path] += 1
        else:
            count_dict[path] = 0

        print(path.format(k=count_dict[path]))

Systemdユニットを作る

起動時にシンボリックリンクを貼ってほしいので、Systemd Unitを作ります。After=systemd-udevd.serviceとすることで、一応udevdが動いてから立ち上がるようにしています。/dev/以下にシンボリックリンクを作りたいため、rootで動くので注意です。

[Unit]
Description=Tuner Symboliclink Script
After=systemd-udevd.service

[Service]
ExecStart=/usr/bin/python3 <Pythonスクリプトの場所>
Restart=no
User=root
Group=root

[Install]
WantedBy=multi-user.target

最後に

ioctlのような低レイヤっぽいのを手軽に叩けるスクリプト言語としてPythonは良いかもしれない。。。

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?