Raspberry Piでダウンロードしたドライバをクロスコンパイルする

# 環境

- ターゲット
    - Raspberry Pi 1 Model A+
    - 2017-11-29-raspbian-stretch-lite
        - Linux raspberrypi 4.9.59+ #1047 Sun Oct 29 11:47:10 GMT 2017 armv6l GNU/Linux
    - PLANEX GW-450D2
        - 5GHz対応
- ホスト
    - Ubuntu 16.04 amd64

# カーネルの準備(ホストにて)

[本家](https://www.raspberrypi.org/documentation/linux/kernel/building.md)を見ながら進める。

## カーネルソースの取得

Raspbianのカーネルに合ったソースを取得する。

```
git ls-remote --tags https://github.com/raspberrypi/linux 
```

ターゲットでの`uname -a`の結果と比較すると、`raspberrypi-kernel_1.20171029-1`かな。
shallow cloneする。

```
git clone --depth=1 -b raspberrypi-kernel_1.20171029-1 https://github.com/raspberrypi/linux
```

## toolchainの取得とパスの設定

```
git clone https://github.com/raspberrypi/tools ~/tools
export PATH=~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH
```

## 環境変数とカーネルの設定

```
cd linux
KERNEL=kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_prepare
cd ..
```

[本家](https://www.raspberrypi.org/documentation/linux/kernel/building.md)によると、Pi 2, Pi 3, or Compute Module 3は`bcm2709_defconfig`とのこと。

# ドライバの準備(ホストにて)

## ドライバソースの準備

GW-450D2は[Linux用ドライバ](https://www.planex.co.jp/support/download/gw-450d2/driver_linux.shtml)が提供されている。また、[開発者向け情報](https://www.planex.co.jp/support/taiou/kisyu/developer_wifiusb.shtml)によると、MT7610Uを使っている。
[MT7610Uのページ](https://www.mediatek.jp/products/mt7610u)からもドライバがダウンロードできる。りんごアイコンとペンギンアイコンが逆というトラップがある。
どちらも同じもののようだ。皆様のご判断で。

```
tar xvjf mt7610u_wifi_sta_v3002_dpo_20130916.tar.bz2
```

## ドライバのパッチ当て

[こちらの記事](https://qiita.com/moutend/items/915f8988dc7d7a8d953f)が大変に詳しい。
記事中のパッチは、現状のRaspbianのカーネルでも、そのまま使えた。

```
git clone https://gist.github.com/moutend/cb35a37297910c99d3e2 gist
./gist/patch.sh
```

`patch.sh`は、ホームディレクトリ直下に`mt7610u_wifi_sta_v3002_dpo_20130916`と`gist`がある事が前提になっているので、ディレクトリ構成が異なる場合は、適宜修正。

## クロスコンパイルの設定

```diff:mt7610u_wifi_sta_v3002_dpo_20130916/Makefile
--- Makefile.orig	2013-09-16 23:03:08.000000000 +0900
+++ Makefile	2018-03-10 22:42:59.896089209 +0900
@@ -32,7 +32,8 @@
 RTMP_SRC_DIR = $(RT28xx_DIR)/RT$(MODULE)

 #PLATFORM: Target platform
-PLATFORM = PC
+PLATFORM = RPI
+#PLATFORM = PC
 #PLATFORM = 5VT
 #PLATFORM = IKANOS_V160
 #PLATFORM = IKANOS_V180
@@ -194,6 +195,14 @@
 CROSS_COMPILE = mips-wrs-linux-gnu-
 endif

+ifeq ($(PLATFORM),RPI)
+LINUX_SRC = ~/linux
+LINUX_SRC_MODULE = ~/linux/drivers/net/wireless/
+CROSS_COMPILE = arm-linux-gnueabihf-
+ARCH := arm
+export ARCH
+endif
+
 ifeq ($(PLATFORM),PC)
 # Linux 2.6
 LINUX_SRC = /lib/modules/$(shell uname -r)/build
@@ -397,9 +406,13 @@
 ifeq ($(PLATFORM),FREESCALE8377)
 	$(MAKE) ARCH=powerpc CROSS_COMPILE=$(CROSS_COMPILE) -C  $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules
 else
+ifeq ($(PLATFORM),RPI)
+	$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C  $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules
+else
 	$(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/os/linux modules
 endif
 endif
+endif

 ifeq ($(OSABL),YES)
 	cp -f os/linux/Makefile.6.netif $(RT28xx_DIR)/os/linux/Makefile
```

```diff:mt7610u_wifi_sta_v3002_dpo_20130916/os/linux/config.mk
--- config.mk.orig	2018-03-10 22:41:30.185274819 +0900
+++ config.mk	2018-03-10 22:42:18.196644267 +0900
@@ -1031,6 +1031,10 @@
 export CFLAGS
 endif

+ifeq ($(PLATFORM),RPI)
+	EXTRA_CFLAGS := $(WFLAGS)
+endif
+
 ifeq ($(PLATFORM),PC)
     ifneq (,$(findstring 2.4,$(LINUX_SRC)))
 	# Linux 2.4
```

合っているかは、謎。

# ドライバのビルド(ホストにて)

```
cd mt7610u_wifi_sta_v3002_dpo_20130916
make
```

`os/linux/mt7650u_sta.ko`ができる。

# ターゲットの設定

[こちらの記事](https://www.planex.co.jp/articles/RaspberryPi_GW-450D/)を見ながら進める。
以下の`4.9.59+`は、Pi 2, Pi 3, or Compute Module 3では、`4.9.59-v7+`になると思われる(未確認)。

## Raspberianの初期設定

```
sudo raspi-config      # update
sudo touch /boot/ssh   # startup sshd automatically
```

## ドライバと設定ファイルをホストからターゲットへコピー

`os/linux/mt7650u_sta.ko`は`/lib/modules/4.9.59+/kernel/drivers/net/wireless/`に、
`RT2870STA.dat`は`/etc/Wireless/RT2870STA/`に、
それぞれコピー。

## ドライバのロード

```
sudo depmod -a 4.9.59+
sudo modprobe mt7650u_sta
```

`ip link`で`ra0`が出てくる。

## APを検索

```
iwlist ra0 scan
```

`Frequency:5.18 GHz (Channel 36)`のように、5GHzも出てくる。

## ネットワークの設定

```/etc/network/interfaces.d/gw-450d2
allow-hotplug ra0
auto ra0
iface ra0 inet dhcp
wpa-ssid "hogehoge"
wpa-psk "hogehoge"
```

```
service networking restart
```

# 宿題
- 5GHz接続の検証
    - AirMacの5GHzにつながらない?
        - W52のはずだが…
- スループットの測定
- 消費電力の測定
- APモードの設定
- MT7601Uドライバで動かす
    - 5GHzは動きませんよねぇ
- 不審な挙動の解析
    - 何かの条件でPi自体がめちゃくちゃ遅くなる?

# 以下おまけ

試しにrt2800usbでやってみた。

## ファームウェアのインストール(一応)

```
sudo apt-get install firmware-ralink
dpkg -L firmware-misc-nonfree | grep rt # list firmware files
```

## VID, PIDの確認

```shell-session
$ lsusb
Bus 001 Device 005: ID 2019:ab31 PLANEX
```

## ソースの確認

```linux/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
        /* Planex */
        { USB_DEVICE(0x2019, 0xab24) },
        { USB_DEVICE(0x2019, 0xab29) },
```

0x2019, 0xAB31 は、無い。

## newid

```shell-session
$ sudo modprobe rt2800usb
# echo 2019 ab31 > /sys/bus/usb/drivers/rt2800usb/new_id
(デバイス抜挿)
$ dmesg
[ 2217.383618] usbcore: registered new interface driver rt2800usb
[ 2310.303754] usb 1-1.2: reset high-speed USB device number 5 using dwc_otg
[ 2310.439197] ieee80211 phy0: rt2800_probe_rt: Error - Invalid RT chipset 0x7650, rev 2000 detected
[ 2310.439220] ieee80211 phy0: rt2x00lib_probe_dev: Error - Failed to allocate device
[ 2384.725637] usb 1-1.2: USB disconnect, device number 5
[ 2386.554302] usb 1-1.2: new high-speed USB device number 6 using dwc_otg
[ 2386.701323] usb 1-1.2: New USB device found, idVendor=2019, idProduct=ab31
[ 2386.701348] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2386.701362] usb 1-1.2: Product: GW-450D
[ 2386.701371] usb 1-1.2: Manufacturer: Planex
[ 2386.701383] usb 1-1.2: SerialNumber: 1.0
[ 2386.814310] usb 1-1.2: reset high-speed USB device number 6 using dwc_otg
[ 2386.949637] ieee80211 phy1: rt2800_probe_rt: Error - Invalid RT chipset 0x7650, rev 2000 detected
[ 2386.949659] ieee80211 phy1: rt2x00lib_probe_dev: Error - Failed to allocate device
```

NICができない。Invalid RT chipsetとのこと。無念。