GW-450DやWN-AC433UKをRaspberry Piで使う

planexのありがたい記事を参考に作業。

環境としてはRaspbian wheezyを仮定。

おおまかな流れ : まず、下準備としてカーネルモジュールのビルドに必要な道具を揃える(既に揃えてある人はスルーしてよい)。続いて、ドライバのソースコードを取得し、必要な変更を加えてからビルド、インストールする。

前提知識

記事執筆時点ではGW-450DやWN-AC433UKはRaspberry Piではそのままでは動作せず、ドライバを自分で導入してやる必要がある。

GW-450DやWN-AC433UKはMediaTekのMT-7610Uというチップセットを用いているので、中身は基本的に同じである。ただし、USBのベンダーIDとプロダクトIDは変更されているので、これをドライバ中に記述してやる必要がある。

下準備1: カーネルビルドに用いられたGCCのバージョンを調べる

ここでは、raspberry piのデフォルトのカーネルを使う場合の下準備の例を示す。Raspbianがaptで提供しているカーネルを使用する場合はこの限りではなく、単にapt-getでヘッダーファイルが含まれるパッケージを取得すればよい。

$ cat /proc/version
Linux version 3.18.5+ (dc4@dc4-XPS3-9333) (gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650) - Linaro GCC 2014.03) ) #746 PREEMPT Mon Feb 2 13:57:16 GMT 2015

で、gcc4.8.3が使われていることがわかったので、gcc4.8系列を使う。

ただし、Linux ARMにとってgcc4.8.0から4.8.2までは "too buggy" で、Linuxを正しくビルドできないとされている(これらのバージョンを使おうとすると、あるヘッダでエラーが出て弾かれるようになっている)ので、これは避ける必要がある。

したがって、この記事の執筆時点では、gcc-4.8.3を用いるのが正解ということになる。

下準備2: gccを入れる

本来であれば、

$ sudo apt-get install gcc-4.8

で目的のバージョンが入るのが望ましい。試しに

$ gcc-4.8 -v

で、所望のバージョンが得られていれば、この節はスキップしてよい。

gcc 4.8 on Raspberry Pi Wheezy | some wide open spaceを参考に、新しいバージョンを入れる。

/etc/apt/sources.listを編集する。nanoと書かれている部分は適宜別のエディタ(vim等)に置き換えてよい。

$ sudo nano /etc/apt/sources.list

debで始まっている行を下にコピペし、wheezyと書いてある行をjessieに直す(←これらはDebianのバージョン)

例えば、

deb http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi
deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi

のように、wheezyの行とjessieの行が共存した状態にする。

続いて、優先度を設定する。

$ sudo nano /etc/apt/preferences

まだこのファイルが無ければ、新しく作成してよい。以下のように編集する。

Package: *
Pin: release n=wheezy
Pin-Priority: 900

Package: *
Pin: release n=jessie
Pin-Priority: 300

Package: *
Pin: release o=Raspbian
Pin-Priority: -10

これで、原則としてwheezyを使うが、必要に応じてjessieを使うという状態になった。

aptのデータベースを更新する。

$ sudo apt-get update

jessieに入っているほうのgcc-4.8をインストールする。

$ sudo apt-get install gcc-4.8/jessie

とすれば良さそうだが、依存関係が壊れると言われるので、必要な依存関係を全て明示してinstallする。例えば、

$ sudo apt-get install gcc-4.8/jessie libmpfr4/jessie cpp-4.8/jessie libgcc-4.8-dev/jessie libgcc1/jessie libc6-dev/jessie libc-dev-bin/jessie libc6/jessie

とする。

念のため、gcc-4.8の依存関係のために書いたやつは自動でインストールしたとマークしておく。

$ sudo apt-mark auto libmpfr4 cpp-4.8 libgcc-4.8-dev libgcc1 libc6-dev libc-dev-bin libc6

下準備3: gccの特定バージョンをデフォルトにする

gccはalternativesに入っていないので、自分で追加する。

例えば、gcc-4.6, gcc-4.8が入っているときは、

$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 20
$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50

のようにする。すると、gcc-4.8が優先度50で最大なのでデフォルトになる。

優先度に関わらず特定のバージョンをデフォルトにしたいときは、

$ sudo update-alternatives --config gcc

で所望のものを選択する。

$ gcc -v

で、所望のバージョン(記事執筆時点では4.8.3)が得られているかどうかを確認する。

下準備4: Linuxソースコードを取得し、ビルドする

rpi-sourceを使って、Raspberry Pi用のLinuxソースコードを取得する。

$ sudo wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source -O /usr/bin/rpi-source && sudo chmod +x /usr/bin/rpi-source && /usr/bin/rpi-source -q --tag-update

ncurses-devを入れておく。

$ sudo apt-get install ncurses-dev

rpi-sourceを実行する。

$ rpi-source

rpi-sourceはカーネルソースを取得して必要な部分をビルドしてくれる。

成功すると、ホームディレクトリにlinuxというフォルダができる。/lib/modulesからここへのシンボリックリンクが貼られるので、これでカーネルモジュール作成の準備が整った。

ソースコードを取得する

mt7610u_wifi_sta_v3002_dpo_20130916.tar.bz2 というファイルを取得する。

MediaTekのサイトから、Linux用のMT7610U USBドライバーを取得するか、PlanexのサイトからLinux用のGW-450Dドライバーを取得する。どちらも同じものである。

これを解凍する。

$ tar jxvf mt7610u_wifi_sta_v3002_dpo_20130916.tar.bz2
$ cd mt7610u_wifi_sta_v3002_dpo_20130916

ドライバに必要な変更を加える

パッチを用意したのでこれを当ててもよい。手動で編集するはら以下のとおり。

linuxバージョンの差異への対応

include/os/rt_linux.hの

typedef struct _OS_FS_INFO_
{
	int				fsuid;
	int				fsuid;
	mm_segment_t	fs;
} OS_FS_INFO;

を、

typedef struct _OS_FS_INFO_
{
	kuid_t				fsuid;
	kgid_t				fsuid;
	mm_segment_t	fs;
} OS_FS_INFO;

と書き換える。

ベンダーID, プロダクトIDの追加

common/rtusb_dev_id.cの

USB_DEVICE_ID rtusb_dev_id[] = {
#ifdef MT76x0
	{USB_DEVICE(0x148F,0x7610)}, /* MT7610U */
	{USB_DEVICE(0x0E8D,0x7610)}, /* MT7610U */

となっている部分に、

USB_DEVICE_ID rtusb_dev_id[] = {
#ifdef MT76x0
	{USB_DEVICE(0x2019,0xAB31)}, /* GW-450D */
	{USB_DEVICE(0x04BB,0x0951)}, /* WN-AC433UK */
	{USB_DEVICE(0x148F,0x7610)}, /* MT7610U */
	{USB_DEVICE(0x0E8D,0x7610)}, /* MT7610U */

と追記する。

WPA Supplicantの設定

os/linux/config.mkの

# Support Wpa_Supplicant
# i.e. wpa_supplicant -Dralink
HAS_WPA_SUPPLICANT=n


# Support Native WpaSupplicant for Network Manager
# i.e. wpa_supplicant -Dwext
HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n

を、

# Support Wpa_Supplicant
# i.e. wpa_supplicant -Dralink
HAS_WPA_SUPPLICANT=y


# Support Native WpaSupplicant for Network Manager
# i.e. wpa_supplicant -Dwext
HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y

に変更する。

設定の変更

conf/RT2870STA.datの

SSID=11n-AP

SSID=

に変更する。また、

AuthMode=OPEN
EncrypType=NONE

AuthMode=WPA2PSK
EncrypType=AES

に変更する。(WPA2PSK/AESを使わない場合にどうすればよいかは未調査)

なぜか、デフォルトではconf/RT2870STA.datではなくconf/RT2860STA.datをインストールするようになってしまっているので、os/linux/config.mkの640行目あたりにある

ifneq ($(or $(findstring mt7650u,$(CHIPSET)),$(findstring mt7630u,$(CHIPSET)),$(findstring mt7610u,$(CHIPSET))),)
WFLAGS += -DMT76x0 -DRT65xx -DRLT_MAC -DRLT_RF -DRTMP_MAC_USB -DRTMP_USB_SUPPORT -DRTMP_TIMER_TASK_SUPPORT -DA_BAND_SUPPORT -DRTMP_EFUSE_SUPPORT -DNEW_MBSSID_MODE -DCONFIG_ANDES_SUPPORT
#-DRTMP_FREQ_CALIBRATION_SUPPORT
#-DRX_DMA_SCATTER
ifneq ($(findstring mt7650u,$(CHIPSET)),)
WFLAGS += -DMT7650
endif

ifneq ($(findstring mt7630u,$(CHIPSET)),)
WFLAGS += -DMT7630
endif

ifneq ($(findstring mt7610u,$(CHIPSET)),)
WFLAGS += -DMT7610
endif

ifneq ($(findstring $(RT28xx_MODE),AP),)
#WFLAGS += -DSPECIFIC_BCN_BUF_SUPPORT
endif

ifeq ($(HAS_CSO_SUPPORT), y)
WFLAGS += -DCONFIG_CSO_SUPPORT -DCONFIG_TSO_SUPPORT
endif

CHIPSET_DAT = 2860
endif

を見つけ(mt7610uと書いてあるのがポイント)、この末尾の

CHIPSET_DAT = 2860

CHIPSET_DAT = 2870

に変更する。

ビルド&インストール

$ make
$ sudo make install

これでインストールされる。

あとは通常の無線LANドングルと同様に使用できる。

アップデートへの対応

rpi-updateでアップデートした場合、新しいカーネルが入ってくることがある。この場合、rpi-sourceを実行して対応するヘッダーファイル等を作成し、ドライバを再度ビルド&インストールすればよい。