🐈

Macで録画チューナーを使えるようにしたい(願望

に公開

はじめに

とりあえず環境を作っただけなのに、記事にしろって知り合いに言われたので……。
マレインさん の recisdb (https://github.com/kazuki0824/recisdb-rs) にドライバ機能をぶち込めないか、という試行錯誤の準備になります。
(VS Code で recisdb の処理の挙動をみつつ、px4_drv の px-w3u4 用処理を libusb で埋め込みたい、という願望)

ひとまず、Mac 上で recisdb を rust の cargo build できるところまで。
運良く libusb を組み込めたら、更新します。

Mac でドライバ作るとか、面倒くさいことこの上ない気しかしない(ので、アプリにUSB制御を突っ込みたい)

2025/8/10 追記
相変わらず、こっち関係に時間が取れてなくて全然ですが、我らがApple様が、Podmanを差し置いて Containerization framework を立ち上げたようで。
で、GitHub で issue を見てみれば、USB support via USB/IP が上がっていまして。
ちゃっちゃと USB passthrough 機能を盛り込んでくれれば、こんな面倒なことをしなくて良くなるんですけどね……。
というわけで、しばらくやる気が低空飛行するだろうなぁ、の気持ち。
10月くらいまでに、進展がなさそうだと、お尻に火がつくかもしれない。

2025/10/12 追記2
Containerization framework の方は動きが見えないですねぇ……。
どうなることやら。
それはそれとして、そのうちの自分用にメモ
(組み込みLinuxデバイスドライバの作り方 (1))
https://qiita.com/iwatake2222/items/1fdd2e0faaaa868a2db2

2026/01/10 追記3
M4 Mac mini を購入したため、そろそろ動かないとマズくなってきた。
Containerization framework の方でちょっとだけ動きがあった。
ChatGPTくんと相談した感じ、Container用Kernelに USB/IPクライアント と PX4_drv が入れられれば、という感じに見えた。
ドライバ機能の取り込みの話は、うん、何もないです……。

2026/01/12 追記4
ちょっと調べてみた感じ、USB/IP の方が微妙だったのと、
お仕事で Copilotくんを使ってみた感じは全然イケてたので、ChatGPTをしばき倒しながら、移植することにした。
一応、下記にちょっとずつ足していければ……。
https://github.com/sakuei-ld/rust_px4_drv
内臓されているRT710にアクセスができるらしいところまでコードは書いたものの、動作確認をしてないので、全くわからん。
あと、recisdb に取り込むと、複数呼び出し時に適切に動かしづらい気がしたので、User space driver として動かす方向性でいきたいと思います。
(結果、Rust を使っているのは、ただの趣味ということに())
まぁ、User space driver としてどうこうは、まだ全く分からないのですが。

Homebrew の準備

公式ページ (https://brew.sh/ja/) を参考にインストール。
忘れたので、特に書けることが無い……。

libpcsc の準備

以下コマンドを実行。

brew install pcsc-lite

recisdb 内で、libpcsclite を pkg-config 経由で参照しているので、Mac 内でアクセスできるようにコピー。

cp /usr/local/opt/pcsc-lite/lib/pkgconfig/libpcsclite.pc /usr/local/lib/pkgconfig/

(注意: Intel Mac でしか確認してないので、M1 Mac だと分からない(多分、パス違うと思う))
(やる気があったら、そっちでも確認します)

Rust の準備

recisdb は、偉大かつ難解な Rust で書かれているので、Rust を準備。

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

brew でも出来るらしい。
which コマンド曰く、/usr/local/binに居るので、多分、このコマンドでやってる、ハズ。

recisdb の準備

まずは git から持ってくる。
(ここでの記載は コミットID: dea64f773e2dc079b112334882fcf4840f5f6eea を想定)
recursive を忘れないように (1敗

git clone --recursive https://github.com/kazuki0824/recisdb-rs.git

細かいパッケージで何を入れなきゃいけないかは、分からん(なんかで色々やってた所為で、brew install をちまちまやってるので)
必要そうなものは、上記のgithubを確認して、自分で頑張って欲しい(すまない……
(clang、cmake、pkg-config くらいだと思うので、多分 brew 入れた時点であると思う)

当たり前ですが、recisdb は Mac に対応してない(する必要もない)ので、ところどころ必要なものが抜けていて、build が出来ない。
で、変える必要がある場所は、下記の3ファイル

  • b25-sys/build.rs
  • recisdb-rs/src/utils.rs
  • recisdb-rs/src/tuner.rs

ついでに、下記のように tuner 下に macos ディレクトリを新規作成し

  • recisdb-rs/src/tuner/macos

tuner 下の linux ディレクトリから、同名のファイルをコピーし macos ディレクトリに配置

  • recisdb-rs/src/tuner/macos/character_device.rs
  • recisdb-rs/src/tuner/macos/mod.rs

変更内容は、基本的には、macos 用内容を記載すること。
で、とりあえず build が通る状態にしたいだけなので、linux 向けの記述をコピーして配置します。
b25-sys/build.rs は 100行目にmacosでも通るように追記。

} else if cx.os.clone().unwrap_or_default().contains("linux") || cx.os.clone().unwrap_or_default().contains("macos") {

recisdb-rs/src/utils.rs は 55行目〜87行目が

// 仮で Linux のものをコピーしてるだけなので、後で対応が必要
    #[cfg(target_os = "macos")]
    pub(crate) fn handle_opening_error(e: io::Error) -> ! {
        if let Some(raw_os_error) = e.raw_os_error() {
            match raw_os_error {
                nix::libc::ENOENT => {
                    error!("The tuner device does not exist.");
                }
                nix::libc::ENODEV => {
                    error!("The tuner device does not exist.");
                }
                nix::libc::EALREADY => {
                    error!("The tuner device is already in use.");
                }
                nix::libc::EBUSY => {
                    error!("The tuner device is busy.");
                }
                nix::libc::EACCES => {
                    error!("Permission denied while opening the device.")
                }
                _ => {
                    error!(
                        "Cannot open the device. (Unexpected Linux error: {})",
                        raw_os_error
                    );
                }
            }
        } else {
            error!("Cannot open the device. (Unexpected IO error: {})", e);
        }
        std::process::exit(1);
    }

128〜162行目がこんな感じ。


    #[cfg(target_os = "macos")]
    pub(crate) fn handle_tuning_error(e: io::Error) -> ! {
        if let Some(raw_os_error) = e.raw_os_error() {
            match raw_os_error {
                nix::libc::EALREADY => {
                    error!("The tuner device is already in use.");
                }
                nix::libc::EBUSY => {
                    error!("The tuner device is busy.");
                }
                nix::libc::ENOTTY => {
                    error!("The tuner device does not support the ioctl system call.");
                }
                nix::libc::EINVAL => {
                    error!("The specified channel is invalid.");
                }
                nix::libc::EAGAIN => {
                    error!("Channel selection failed. The channel may not be received.");
                }
                nix::libc::EACCES => {
                    error!("Permission denied.")
                }
                _ => {
                    error!(
                        "Cannot tune the device. (Unexpected Linux error: {})",
                        raw_os_error
                    );
                }
            }
        } else {
            error!("Cannot tune the device. (Unexpected IO error: {})", e);
        }
        std::process::exit(1);
    }

これも、osごとの処理について、macos 用のものを生やしてる。
で、recisdb-rs/src/tuner.rs は、3〜16行目が下記みたいになるようにする。

#[cfg(target_os = "linux")]
pub use self::linux::{Tuner, UnTunedTuner};
#[cfg(target_os = "windows")]
pub use self::windows::{Tuner, UnTunedTuner};
#[cfg(target_os = "macos")]
pub use self::macos::{Tuner, UnTunedTuner};

#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "macos")]
mod macos;

と、いうわけで、linux向けの箇所をコピーして、ペーストして、macos 用の箇所として増やすだけ。
これで、build が通るようになるハズ。
まぁ、ドライバが無いので、checksignal と tune は、多分エラー吐いて落ちる。
help と version は動く。
もしかしたら、decodeは動くかもしれん(いい感じのデータが無いので試せない)

仮版の終わりに

あとは、VS Code のデバッグ機能を使いながら、挙動を確認しつつ、px4_drv の pxシリーズ向け機能 + libusb の機能 に置き換えていけば、いいハズ。
libusb は、cargo add libusb1-sys で入れつつ、https://github.com/a1ien/rusb/tree/master/libusb1-sys/examples を見ると、とりあえず usbデバイスの走査方法くらいは分かる。
どう IO するのかは、分からん……。
これから調べます。

というわけで、雑な感じですが、ひとまずのまとめ、ということで。
時間が欲しいなぁ……。

Discussion