iPad Pro から Raspberry Pi 4 (Arch Linux ARM aarch64) を USB ガジェットとして使用する方法

## はじめに

Raspberry Pi 4 は USB-C ポートを Ethernet として使うことが可能であるため、USB-C ポートを持つ iPad Pro と組み合わせると、USB-C ケーブル一本で iPad Pro から Raspberry Pi に給電しつつそのケーブルを通して SSH 接続することができます。これにより、iPad Pro 単体では難しい部分 (Rust コードをコンパイルする、Docker を動かす、Linux 環境で何かをテストする) などをさくっと Raspberry Pi 4 をアクセサリとして挿すだけで補完することができるようになります。

![IMG_0353.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10478/0cfdad9a-a570-ad88-6d83-f28ca6f5967a.jpeg)

この記事では、 Raspberry Pi 4 の OS として Arch Linux ARM (aarch64) を使用する場合の手順を書いています。Raspbian を使用している人も最後の参考情報に書いている元記事を参考にすることでうまくいくはずです。

この記事では iPad Pro 側の SSH クライアントとして [Blink Shell](https://apps.apple.com/jp/app/blink-shell-mosh-ssh-client/id1156707581?l=en) を利用していますが、無料アプリであれば [Termius](https://apps.apple.com/jp/app/termius-ssh-client/id549039908?l=en) などでも大丈夫だと思います。

## Raspberry Pi 4 のブート用 SD カードの準備

今回私は https://github.com/hsxsix/archlinuxarm-aarch64-rpi からディスクイメージをダウンロードして SD カードに焼きました。

既存の Linux 環境をお持ちの方は https://olegtown.pw/Public/ArchLinuxArm/RPi4/rootfs/ から rootfs をダウンロードして https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-4 の手順を参考に SD カードのパーティションを作成するのもありかもしれません。

### 実際に行った手順 (macOS の場合)

SD カードは事前に Mac に挿入しておきます。

```shell
cd Downloads
curl -LO https://file.hsxsix.com/other/archlinuxarm-aarch64-rpi.img
diskutil list # ここで SD カードがどのディスク番号に割り当てられているかを確認する (今回は /dev/disk2 だった)
diskutil umountDisk /dev/disk2
sudo dd if=archlinuxarm-aarch64-rpi.img of=/dev/rdisk2 bs=1m
diskutil eject /dev/disk2
```

## Raspberry Pi 4 の初回起動

この時点では Raspberry Pi 4 は有線でしかネットワークに接続できないので、私は Wi-Fi のセットアップが終わるまではディスプレイとキーボードを Raspberry Pi に接続して初期設定を行いました。

初期状態では root ユーザのパスワードが root になっているので、それでログインします。

まずは https://github.com/hsxsix/archlinuxarm-aarch64-rpi で最初に必ず行うように書かれている手順を実行します。

```shell
init_resize
```

これによりルートファイルシステムの空間が拡張されます。その後、自動で再起動されるので、再起動後に作業を継続します。

## Wi-Fi の設定

まずはインターネットに接続できるようにするため Wi-Fi の設定から行います。

```shell
# このディスクイメージで用意されている wpa_supplicant 関連の設定を一旦リセット
rm /boot/wpa_supplicant.conf
rm /etc/wpa_supplicant/wpa_supplicant.conf
systemctl stop wpa_supplicant
systemctl disable wpa_supplicant

# https://wiki.archlinux.org/index.php/WPA_supplicant#Connecting_with_wpa_cli に従って wpa_cli で設定
vi /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
# 以下を書く
# ctrl_interface=/run/wpa_supplicant
# update_config=1
wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
wpa_cli
```

`wpa_cli` を実行すると以下のように対話的に設定していくことができます。

```
> scan
OK
> add_network
0
> set_network 0 ssid "ここに SSID"
> set_network 0 psk "ここに Wi-Fi のパスワード"
> enable_network 0
> save_config
OK
> quit
```

完了したら systemd-networkd 側の設定ファイルを作成しておきます。

```shell
vi /etc/systemd/network/25-wireless.network
```

ファイルの中身は以下のように書いておきます。(https://wiki.archlinux.org/index.php/Systemd-networkd#Wireless_adapter を参考)

```
[Match]
Name=wlan0

[Network]
DHCP=ipv4
```


完了したら、有効化します。

```shell
systemctl start wpa_supplicant@wlan0
systemctl enable wpa_supplicant@wlan0
systemctl restart systemd-networkd
ip a # wlan0 に IP アドレスが降ってきていることを確認する
```

## 初期設定

今回使用したディスクイメージ特有の設定がいくつか施されているので、それをノーマルな状態に戻していきます。

```shell
vi /etc/pacman.d/mirrorlist
# Geo-IP based mirror selection and load balancing のミラーサーバが一番上に来るように、それより上にある行を削除する
vi /etc/pacman.conf
# 末尾付近にある aur などは見にいく必要がないので削除
```

以降は一般的な初期設定です。

```shell
pacman -Syyu # パッケージデータベースの同期とパッケージのアップグレード
passwd # root ユーザのパスワード変更
pacman -S sudo
hostnamectl set-hostname Raspberry-beetle # ホスト名の設定 (mDNS ではこのホスト名 + .local が使用されるので短めがおすすめです)
timedatectl set-timezone Asia/Tokyo
visudo
# wheel グループのユーザに sudo 権限を与えるために以下の行を有効化しておく
# %wheel ALL=(ALL) ALL
```

## 一般ユーザ作成

私は kebo という名前のユーザを作成しましたが、好きなユーザ名に読み替えて実行してください。

```shell
useradd kebo # ユーザ作成
passwd kebo # パスワード設定
usermod -aG wheel kebo # wheel グループに所属させる (sudo 実行のため)
mkdir /home/kebo # ホームディレクトリ作成
chown kebo:kebo /home/kebo # ホームディレクトリの所有権変更
```

## mDNS 設定

Avahi を使って mDNS が使えるようにしておきます。これを行うことによって iPad Pro から Raspberry Pi 4 に対して USB-C ケーブル経由でアクセスするときにホスト名 + .local で名前解決できるので格段に手順が楽になります。

```shell
pacman -S avahi
systemctl start avahi-daemon
systemctl enable avahi-daemon
```

確認する際は iPad Pro の [Blink Shell](https://apps.apple.com/jp/app/blink-shell-mosh-ssh-client/id1156707581?l=en) を開いて

```console
blink> ping Raspberry-beetle.local
PING raspberry-beetle.local (192.168.86.46): 56 data bytes
64 bytes from 192.168.86.46: icmp_seq=0 ttl=64 time=207.943 ms
64 bytes from 192.168.86.46: icmp_seq=1 ttl=64 time=11.601 ms

--- raspberry-beetle.local ping statistics ---
3 packets transmitted, 2 packets received, 33.3% packet loss
round-trip min/avg/max/stddev = 11.601/109.772/207.943/98.171 ms
```

のように「ホスト名 + .local」から ping の応答が返ってくれば成功です。

## USB ネットワークインターフェイスを生やす

ここがこの記事の一番のキモです。これにより iPad Pro と Raspberry Pi 4 が USB-C ケーブルを通して Ethernet で通信できるようになります。

```shell
echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt
sudo vi /root/usb0.sh
# https://gist.github.com/kkk669/0c7b044ad9d992a41ed02467bb0d2d71 の内容をコピペしてください
sudo chmod +x /root/usb0.sh
sudo vi /etc/systemd/system/usb0.service
# https://gist.github.com/kkk669/2ea06a0ca07b16d50e9f5e81e775f045 の内容をコピペしてください
sudo systemctl daemon-reload
sudo systemctl enable usb0
sudo reboot
```

再起動後に以下のように `usb0` というネットワークインターフェイスが増えていることが確認できるかと思います。

```console
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether dc:a6:32:70:5d:1c brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether dc:a6:32:70:5d:1e brd ff:ff:ff:ff:ff:ff
    inet 192.168.86.46/24 brd 192.168.86.255 scope global dynamic noprefixroute wlan0
       valid_lft 85755sec preferred_lft 74955sec
    inet6 fe80::758:6bed:b2a3:76f1/64 scope link 
       valid_lft forever preferred_lft forever
4: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:dd:dc:eb:6d:a1 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::35b2:6f4e:23a2:c0ff/64 scope link 
       valid_lft forever preferred_lft forever
```

## SSH 接続テスト

iPad Pro と Raspberry Pi 4 を USB-C to USB-C ケーブルで接続します。

iPad Pro の Wi-Fi や Cellular 通信をオフにして、[Blink Shell](https://apps.apple.com/jp/app/blink-shell-mosh-ssh-client/id1156707581?l=en) から

```shell
ssh kebo@Raspberry-beetle.local
```

などで SSH 接続できれば成功です。

## (おまけ) スワップファイルの設定

Raspberry Pi 4 でいろいろなものをビルドしたりするとどうしてもスワップがないと辛いため、スワップファイルの設定を行っておきます。ここでは [systemd-swap](https://wiki.archlinux.org/index.php/Swap#systemd-swap) を使用して自動設定させます。

```shell
sudo pacman -S systemd-swap
sudo vi /etc/systemd/swap.conf
# swapfc_enabled=1 に変更
# swapfc_force_preallocated=1 に変更
# zswap_enabled=0 に変更 (今回使用するカーネルではサポートされていないとエラー表示されるため)
sudo systemctl start systemd-swap
sudo systemctl enable systemd-swap
```

しばらくすると以下のコマンドでスワップファイルが作成されていることが確認できます。

```shell
swapon --show
```

![IMG_0353.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10478/0cfdad9a-a570-ad88-6d83-f28ca6f5967a.jpeg)

## 参考情報

- [Pi4 USB-C Gadget - Ben's Place](https://www.hardill.me.uk/wordpress/2019/11/02/pi4-usb-c-gadget/)