ラズパイ Zero WやRasPi 3B 用に5GHz対応のUSB Wi-Fiアダプタ(GW-450D2)のドライバを作る方法。Raspbian Stretch 9.4(Kernel 4.14.34+)でカーネルの全ビルド不要!

2018年5月13日

どもー、GW前半を全てラズパイに捧げたマークです。

Raspbian Stretchの最新カーネル(4.14.34+)で5GHzのWi-Fiを使えるようにと試行錯誤をしまくっていて、ようやくゴールにたどり着きました!

以前やったときに比べて格段に楽になっています。

 

使った物と前準備

  • Raspberry Pi Zero W
  • NOOBSでインストールしたRaspbian Stretch 9.4(Kernel 4.14.34+)Lite

※Raspberry Pi 3Bはカーネルバージョンが違いますが、本記事で紹介する方法で同じように作れば使えるようになります。

SSHで接続できるようにしてあると楽です。
(内蔵Wi-Fiか、外付けUSB-Ethernetアダプタで接続。)

もしくは、ディスプレイとキーボードを接続してもOK。
細かいセットアップ方法は省略!※詳しくはこちらの記事無線LANがすぐ使える! Raspberry Pi Zero W のセットアップ NOOBS GUI編)見てください。

 

Raspbianを最新にアップデート

いつものようにまず更新します。

$ sudo apt-get update
$ sudo apt-get -y upgrade
$ sudo apt-get -y dist-upgrade

再起動します。

$ sudo reboot

バージョンを確認します。

$ uname -a
 Linux rpi-zw2 4.14.34+ #1110 Mon Apr 16 14:51:42 BST 2018 armv6l GNU/Linux
$ cat /etc/debian_version
 9.4

ちなみに、RasPi 3Bunam -rを見ると「4.14.34-v7+」でした。

 

ドライバのビルドに必要なものをインストール

ドライバを作るためのビルド環境を準備していきます。

ビルドツールとカーネルヘッダーを揃える

aptを使ってraspberrypi-kernel-headersを入手するのがポイントです。

これにより、実行中のカーネルとドライバのバージョンが合わない!と挫折しなくてすみますw
(「insmod: ERROR … Invalid module format」 を何度見たことかw)

$ sudo apt-get install build-essential
$ sudo apt-get install raspberrypi-kernel-headers

確認すると、ドライバのビルドに必要な情報が展開されていることがわかります。

$ ls -l /lib/modules/`uname -r`/ | head -3 | tail -2
 lrwxrwxrwx 1 root root 31 4月 17 21:07 build -> /usr/src/linux-headers-4.14.34+
 drwxr-xr-x 11 root root 4096 4月 30 21:52 kernel

Module.symvers もしっかり入ってます。

$ ls /lib/modules/`uname -r`/build/Module.symvers
 /lib/modules/4.14.34+/build/Module.symvers

Makefileには実行中のカーネルと同じバージョンが指定されています。

$ cat /lib/modules/`uname -r`/build/Makefile | head -5
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 4
 PATCHLEVEL = 14
 SUBLEVEL = 34
 EXTRAVERSION =

 

gcc-4.8 を使えるようにする

gcc-4.9は、新しいカーネルになった時にうまくいかずに断念!
(これにどれだけ時間を使ったか。。。)

おとなしく、gcc-4.8を入れます(後記に経緯あり)。

$ sudo apt-get -y install gcc-4.8

gcc-4.8を使うように優先順位を上げます。

$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 60

バージョンを確認します。

$ gcc --version | head -1
gcc (Raspbian 4.8.5-4) 4.8.5

gcc-4.8になってます!

 

ドライバのビルドとインストール

ビルド環境が整ったので、ドライバを入手してビルドしていきます。

ドライバの入手

パソコンなどでPlanexの公式サイトにアクセスし、GW-450D2Linux版ドライバをダウンロードします。

ドライバzipファイルをDLして展開します。

unzip gw-450d2_driver_linux_v3002.zip

中にある、mt7610u_wifi_sta_v3002_dpo_20130916.tar.bz2 をラズパイにコピーします。(USBメモリでもscpでもなんでも良いです)

ここからは、piユーザーのホームディレクトリ(/home/pi/)で作業を行っていきます。

先ほどコピーしたファイルを展開します。

$ tar xf mt7610u_wifi_sta_v3002_dpo_20130916.tar.bz2

tarxfとだけ指定すれば、ファイルの圧縮形式を自動で判別して展開してくれます(豆知識

楽ちん!

 

パッチをあてる

ドライバのソースに、GW-450D2用の修正を加えていきます。

修正パッチを公開してくださっているので、ありがたく頂戴(git clone)します。

piのホームに戻ってgit cloneします。

$ cd
$ git clone https://gist.github.com/moutend/cb35a37297910c99d3e2 gist

そして、kernelバージョンが4.14の場合は、パッチに修正を加えます。

適当なエディタで gist/rt_linux.c.patch を開き、11行目「__vfs_read」「kernel_read」に書き換えます(※)。

修正前

+ return __vfs_read(osfd, pDataPtr, readLen, &osfd->f_pos);

修正後

+ return kernel_read(osfd, pDataPtr, readLen, &osfd->f_pos);

コチラのサイトのコメント欄で解決法が見つかりました!
ありがとうございます!

 

修正が終わったら、ドライバのソースにパッチを当てます。

ホームディレクトリで、

$ ./gist/patch.sh

以下のように表示されたら完了です。

patching file /home/pi/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux/rt_linux.c
 patching file /home/pi/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux/config.mk
 patching file /home/pi/mt7610u_wifi_sta_v3002_dpo_20130916/include/os/rt_linux.h
 patching file /home/pi/mt7610u_wifi_sta_v3002_dpo_20130916/conf/RT2870STA.dat
 patching file /home/pi/mt7610u_wifi_sta_v3002_dpo_20130916/common/rtusb_dev_id.c
 Successfully done.

これでソースの準備が整いました!

 

makeしてインストールする

ドライバーのディレクトリに移動して、makeします。

$ cd ~/mt7610u_wifi_sta_v3002_dpo_20130916/
 $ make

RasPi Zero W で、17分ほどかかりました。
ちなみにRasPi 3B だと5分ぐらいで終わります。

インストールします。

$ sudo make install

念のため再起動します。

$ sudo reboot

 

モジュールがロードされているかを確認する

基本的にはudevがデバイスの接続を認識して自動的にドライバがロードされます。

再起動後に無線LANアダプタ(GW-450D2)を接続して確認します。

$ lsmod |grep mt
 mt7650u_sta 968232 1

しっかりと、読み込まれていました!

ipコマンドで確認します。

$ ip a

ra0」として認識されていました。

 

5GHz帯の無線LANアクセスポイントに接続する

いくつか方法があります。

ググると古い方法(/etc/network/interfacesに直書きしている)が多いのですが、比較的現代風の方法で設定ファイルを手書きする方法で接続します。

アクセスポイントを見つける

まず、コマンドを使ってアクセスポイント(AP)を探します。

$ sudo iwlist ra0 scan

最初の実行だと一部しか出てこないかもしれません。
少し時間を空けて実行すると、ずらずらと出てくると思います。

$ sudo iwlist ra0 scan | grep GHz
 Frequency:2.412 GHz (Channel 1)
 Frequency:2.432 GHz (Channel 5)
 Frequency:2.442 GHz (Channel 7)
 Frequency:2.442 GHz (Channel 7)
 Frequency:2.447 GHz (Channel 8)
 Frequency:2.457 GHz (Channel 10)
 Frequency:2.462 GHz (Channel 11)
 Frequency:2.462 GHz (Channel 11)
 Frequency:5.18 GHz (Channel 36)
 Frequency:5.18 GHz (Channel 36)
 Frequency:5.68 GHz (Channel 136)
 Frequency:5.5 GHz (Channel 100)
 Frequency:2.432 GHz (Channel 5)
 Frequency:2.452 GHz (Channel 9)

2.4GHz帯はたくさんありますね。。。

SSIDで並べたいときは以下のコマンドを実行します。

$ sudo iwlist ra0 scan |grep ESSID

試しに接続してみる

無事に目的とするAPが見つかったら、iwconfigコマンドで接続してみます。

$ sudo iwconfig ra0 essid ${SSID} key s:${PASS}

${SSID}${PASS}は、接続しようとしているAPの設定に置き換えてください。

上手くいっていれば iwconfig ra0 を実行した時に該当するSSIDと周波数(5GHz帯)が表示されます。
※まだ何も設定を書いてないのでIPは自己割当アドレスになっていると思います。

うまく接続できるようなら、以下のコマンドを実行して設定を保存します。

$ sudo sh -c 'wpa_passphrase ${SSID} ${PASS} | grep -v "#psk=" >> /etc/wpa_supplicant/wpa_supplicant.conf'

 

設定プロファイルを作る

次に設定プロファイルを作成します。

/etc/network/interfaces.d/ に設置したファイルを読み込むようになっているので、ra0用にファイルを作ります。

$ sudo vim /etc/network/interfaces.d/ifcfg-ra0

中身は以下の通りです。DHCPでIPを取得します。

allow-hotplug ra0
iface ra0 inet dhcp
 wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

保存して終了したら、インターフェースを起動します。

$ sudo ifup ra0
 Internet Systems Consortium DHCP Client 4.3.5
 Copyright 2004-2016 Internet Systems Consortium.
 All rights reserved.
 For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/ra0/00:xx:xx:xx:xx:xx
 Sending on LPF/ra0/00:xx:xx:xx:xx:xx
 Sending on Socket/fallback
 DHCPDISCOVER on ra0 to 255.255.255.255 port 67 interval 6
 DHCPDISCOVER on ra0 to 255.255.255.255 port 67 interval 13
 DHCPREQUEST of 192.168.0.31 on ra0 to 255.255.255.255 port 67
 DHCPOFFER of 192.168.0.31 from 192.168.0.1
 DHCPACK of 192.168.0.31 from 192.168.0.1
 bound to 192.168.0.31 -- renewal in 290 seconds.

こんな感じでDHCPを使ってIPアドレスが割り当てられます。

やったー!

なお、自宅で普通に使う用途であれば、固定IPを設定する必要は無いと思っています。SSHで接続するときはコチラの記事が参考になると思います。

 

まとめ: Raspberry Pi Zero W 用にGW-450D2のドライバを作る方法

最新のRaspbian Stretch用ドライバを作る時のポイントです。

  • aptでdist-upgradeする & raspberrypi-kernel-headers を入れる。
  • gcc-4.8を使う。
  • kernelバージョンが4.14の場合、ドライバソースの修正パッチで「__vfs_read」を「kernel_read」にする。

これで、新しいカーネルでもGW-450D2を使って5GHz帯のWi-Fiに接続できるようになりました!

5GHz帯のWifiに対応したRaspberry Pi 3B+が日本で使えるようになる(技適マークがついたやつが出る)までのつなぎができました(^o^)

それではみなさん、よいラズパイ生活を!

 

謝辞と後記

この方法を確立するまでに大変参考にさせていただいたサイトです!
ありがたや〜。

見ていただくとわかる通り、まーくのブログを参照していただいております!^^
(嬉しいです!)

以前はgcc-4.9にこだわっていたのですが、カーネルバージョンとの解離が激しく、、、メーカーがメンテしていないソースを個人でメンテするのは不毛すぎる、、、と考え直し、目的を達成することを第一優先にしました。
(昔のソースだから、その時の環境でビルドしないとね!(^^ゞ)

それから、今回はドライバビルドの基本に返って地道にやったので、他のドライバや別カーネルでも応用が利くと思われます。

ゴールデンウイーク前半にさんざん悩まされたカーネルバージョンの違いであれこれ調べた結果、githubで公開されているrpi-4.14.yのカーネルソースツリーを使うと、バージョンがLinux 4.14.39(記事公開時)なのでビルド後にinsmodでこける(insmod: ERROR … Invalid module format)とか、かなり勉強になりました。

コチラの記事ではrpi-update と dist-upgrade の違いなどもよくわかりました。

rpi-updateそのものもは知らなかったのですが、公式の情報通りdist-upgradeがベストです!

有益な記事を公開してくださっているみなさま、ありがとうございました!