Raspberry pi 4 に iPhone をLightningケーブルでつなぐとFTP経由で中身がみれる仕組みを作ったはなし

このAI時代に個人ブログを残すことの意味はあるのかと思いつつ。色々苦労したことを内に留めておくよりかはこうやって吐き出すことでスッキリするという側面もあるかなと思ったので書いてみる。

どういうものを作ったのか?

iPhone を Lightningケーブルで Raspberry Pi 4 に接続すると FTP経由でパソコンから iPhone の中身が見れるシステムを作成しました。また、USBメモリの中身も Raspberry Pi 4 に挿すと FTP経由で見ることができます。

なぜ作ったのか?

とある現場では セキュリティの関係上、許可されていないデバイスをパソコンに接続することができないようになっており、パソコン間のデータのやり取りがネットワーク経由でなければならないが、ネットワークもセグメントが異なっているようなケースでは受け渡しが不便なのでローカルエリアに限った場合であればFTPサーバーのようなゲートウェイ機器を接続することでデータの受け渡しをスムーズにできるのではないか?という技術的興味があった。

仕組み

先に述べたとおりではありますが、iPhoneRaspberry Pi 4 に挿すと, /run/media/iphoneiPhone がマウントされます。 FTPサーバーは /run/media をルートディレクトリとしているので、FTPクライアントからは /iphone フォルダが見えます。画像データを見たければ /iphone/DCIM フォルダを見ればその中にあります。USBメモリもほとんど同じしくみで動作していて、USBメモリを挿すと /run/media/system の下に USBメモリのラベル名でフォルダが作成されます。

iPhoneの接続部分

iPhoneUSBメモリのようにデフォルトではマウントできないので、ChatGPTに 「iPhone を USB でつないで、写真(DCIM内の画像)を自動転送 or 任意操作で転送できるようにするには」という問いを投げました。そうすると以下のように答えてくれました。

必要なソフトウェアスタック

  1. libimobiledevice Apple のプロトコル(usbmuxd, lockdown, afc, etc.)を扱う OSS ライブラリ。
  2. usbmuxd iOS デバイスと USB 越しに通信するためのデーモン。libimobiledevice の基盤。
  3. ifuse(任意) iPhoneFUSE を使ってマウントできる CLI ツール(内部に afc を利用)。
  4. udev + usbutils(任意) USB接続検知などに必要。

libmobiledevice については以下のリンクにソースがあります。 github.com

このあたり、 Yocto を構築してよしなにやってくれるようにしたので、いまいち仕組みがわかっていませんが私が作成した Yocto のレシピは以下のリンクのあたりに置いてあります

github.com ⇡これなんで必要だったかもはや覚えてないですが、これがないとおそらく iPhone を認識するデーモンが起動してくれないんだと思います。

github.com ⇡こっちが iPhone をマウントしている本体で、シェルスクリプトの中でやってます。 idevicepair というコマンドを使うと iPhone をペアリングするので、ペアリングがスタートしたら iPhone 側で許可してあげる必要があります。(この動作は Windows を使ってても同じ)

ラズパイを起動して、iPhone を挿すと「このコンピューターを信頼しますか?」と出るので「信頼」を選択して、iPhoneのパスコードを入力すると画面上の [iPhone Status] のところが mounted になり iPhone を認識したことを示します。その状態で FTPクライアントから 192.168.1.254 にアクセスすると iPhone の中身が見えます。あとは iphone/DCIM の下にあるファイルを取ってくれば、iPhoneからデータが吸い出せるという寸法です。

USBメモリ

github.com

USBメモリを自動でマウントするために、Linux の udev という仕組みを利用します。 /etc/udev/rules.d/ の下にルールファイルを置いておくと、そのルールに従ってUSBを認識したときにいろんなことを実行してくれます。今回は /dev/sd* ができたタイミング (USBメモリが機器に挿入されたタイミング) でサービスを起動するようにしていて、そのサービスの中で自動マウントを実行しています。もしかするとなにか抜けがあって認識できなかったりするかもですが、認識すると画面上の [USB storage status] のところにUSBのラベル名が表示されます。FTPクライアントで見たときも同様のラベル名で表示されます。

FTPサーバー

github.com

FTPサーバーは Go を使って書いています。と言っても go-ftpserver っていうまんまのパッケージがあってそれをビルドしただけです。 ftpserver.json に色々設定がかけて、匿名接続にも対応しているのでお手軽につなぎたいときは重宝しています。この go-ftpserver をサービス化して実行するだけのレシピが上のリンクのやつです。ここはそんなに説明することないかな?

LCD出力

LCDディスプレイは以下のものを使用しました。後で書くかもですがタッチパネルも搭載しているタイプです。あと表示はHDMIでつないで表示するタイプです。

https://www.amazon.co.jp/dp/B01N5HW3BP?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1

つないでそのまま表示すると3.5インチなので文字が潰れて全然見れないので、480x320サイズまで解像度を落とす必要がありました。

local.conf に以下のように記述するといい感じに表示されるようになります。

github.com

それができたら、フレームバッファに描画したくなったわけなんですが、その前に画面上にログがびゃーっと出てきたり、ログインプロンプトが出たりするのがいやだったのでそれを無効化する設定を入れました。

↓こっちはログが出るのを抑える設定 github.com

↓こっちはログインプロンプトを抑制する設定。gettyサービスを無効化しています。 github.com

その後で、フレームバッファに画像だしたり、文字出したりするプログラムを作ってそれをサービス化して起動時に表示するようにしました。

github.com

タッチパネル

ここまでできると結構やりたいことはできてたんですが、電源をブチぎりしないと電源が切れないので、ちょっと嫌でした。というのも、ラズパイって電源ブチ切りするとSDカードを破損する可能性があるらしく、最悪起動しなくなるらしいんですよね。それを解決する方法としては、RAMディスク化して、その中で動作させる方法があるんですが、ちょっと私には敷居が高かったので、それだったら、タッチパネルで終了ボタン的なのを実装して、終了ボタンを押したら、 shutdown -h now コマンドを実行して終了させればいいやという発想になりました。

ただ、ボタン作って、そこが押されているかどうかを実装するのはそれはそれで手間だったので(LVGLとか入れてやろうと思ったんですがうまく行かず) 折衷案として、画面を5秒押し続けていたらシャットダウンするという仕組みをいれました。

github.com

これで、安心して電源を切れるようになりました。

まとめ

ラズパイを使って、iPhoneの写真データをFTP経由で吸い出すツールを作成しました。 Raspbian を使っても良かったんですが、組み込みっぽい作り方も学んでみたいと思ったので Yocto に入門して色々試しながら作ってみたのですが、案外すんなり作れたかなという印象でした。レシピという形で構成することで流用が効くため、次別のものを作成するときには参考にできるリポジトリができたかなと、自分の中では満足できる出来でした。