2013-08-08

まとめ ― Ubuntu 12.04 で VIA VNT6656 USB Wifi Module を使えるようにした

ついに完動するに至ったのでまとめておきます。いちおう言っときますが無保証です。

1. 準備

Cコンパイラとかカーネルヘッダとかインストールしておいてください。

2. VIA ドライバのコンパイル

(1) ソースコードを取得

http://www.viaembedded.com/en/products/boards/1890/1/VNT6656_USB_Module_/_Dongle.html
にある VT6656_Linux_src_v1.21.03_x86_11_04.zip です。

$ unzip VT6656_Linux_src_v1.21.03_x86_11_04.zip
$ cd VT6656_Linux_src_v1.21.03_x86/
 

(2)  修正

そのままではコンパイルできないので直します。

--- VT6656_Linux_src_v1.21.03_x86/driver/Makefile    2009-09-07 09:53:36.0000
00000 +0900
+++ work-vt6656/driver/Makefile    2013-08-07 01:51:32.655889247 +0900
@@ -24,7 +24,7 @@
 endif

 # check kernel version
-KVER := $(shell uname -r | cut -c1-3 | sed 's/2\.[56]/2\.6/')
+KVER := $(shell uname -r | cut -c1-3 | sed 's/2\.[56]\|3\.2/2\.6/')
 KERVER2=$(shell uname -r | cut -d. -f2)

 ifeq ($(KVER), 2.6)

diff -ur VT6656_Linux_src_v1.21.03_x86/driver/main_usb.c work-vt6656/driver/main
_usb.c

--- VT6656_Linux_src_v1.21.03_x86/driver/main_usb.c    2011-08-03 11:53:08.0000
00000 +0900
+++ work-vt6656/driver/main_usb.c    2013-08-07 02:23:35.573424483 +0900
@@ -387,7 +387,9 @@
     .ndo_stop        = device_close,
     .ndo_get_stats        = device_get_stats,
     .ndo_start_xmit        = device_xmit,
+#ifdef HAVE_MULTICAST
     .ndo_set_multicast_list    = device_set_multi,
+#endif
     .ndo_do_ioctl        = device_ioctl,
 };
 #endif

[追記:KVER マクロは、将来の Linux の別バージョンでは修正が必要です。要は "2.6" という値になりさえすればいいので、カーネル 2.4 以前を使わないならば、 KVER := 2.6 で十分です。]

(3) ビルド・インストール

config.h は無いので作りました。
# touch /usr/src/linux-headers-3.2.0-51-generic-pae/include/linux/config.h
[追記: いきなりインストールが心配なら、 make install のかわりに非特権ユーザでただ make してみるとよいです。]
# make clean
# make install
このへんで一度 insmod とか試してみるんでしょう。

(4) 設定

[追記: これは、モジュールにネットワークインターフェイス名(今回は eth0 が既にあったので eth1 にしました)。を割り当て、ついで、ブート時に vntwusb が読みこまれるようにします] 
# cat /etc/modules.conf        <-- なければ作る
alias eth1 vntwusb
# cat /etc/modules             <-- これも
lp
vntwusb
[追記:これでリブートしてみるのがいいでしょう。リブートしたくなければ、特権ユーザで modprobe vntwusb とします]

あとは、Ubutuのドキュメントでもみてください。

2013-08-07

モジュールのビルド つづき

何もしないモジュールの例
http://wiki.bit-hive.com/tomizoo/pg/Loadable%20Kernel%20Module%A4%CE%BA%EE%A4%EA%CA%FD
を試してみたら、カーネル 3.2.0 でもプログラムと Makefile は動作した。
(ただし、config.h は先日のインチキなので、これからはよしたほうがいいだろう)。

つまり、モジュールのファイル名が *.ko になったとか、そういった特徴はカーネル 2.6 のころから変わっていないわけだ。

そうおもって VNT6656 ドライバの Makefile を読み直してみると、なぜ全然まともなビルドプロセスにならないかが見えてきた。

この Makefile は、uname -r を sed でホゲってカーネルバージョンをとりだして、それで gmake の ifeq を使って分岐しているんだが、そこで 2.6 決め打ちをしているのである。そんなら話は簡単、強引に 2.6 という文字列を作らせてしまえばいいのである。

27c27
< KVER := $(shell uname -r | cut -c1-3 | sed 's/2\.[56]/2\.6/')
---
> KVER := $(shell uname -r | cut -c1-3 | sed 's/2\.[56]\|3\.2/2\.6/')
ここで、 sed の正規表現での A or B は A\|B ということに注意。はまる。

これで make から make -C なんちゃらを呼ぶプロセスに入る。

次のエラーは、ずっとまっとうである。

$ make
make -C /lib/modules/3.2.0-51-generic-pae/build SUBDIRS=/home/toyoda/work-vt6656/driver modules
make[1]: Entering directory `/usr/src/linux-headers-3.2.0-51-generic-pae'
  CC [M]  /home/toyoda/work-vt6656/driver/main_usb.o
/home/toyoda/work-vt6656/driver/main_usb.c:390:2: error: unknown field 'ndo_set_multicast_list' specified in initializer
/home/toyoda/work-vt6656/driver/main_usb.c:390:2: warning: initialization from incompatible pointer type [enabled by default]
/home/toyoda/work-vt6656/driver/main_usb.c:390:2: warning: (near initialization for 'vntwusb_netdev_ops.ndo_select_queue') [enabled by default]
/home/toyoda/work-vt6656/driver/main_usb.c: In function 'device_set_multi':
/home/toyoda/work-vt6656/driver/main_usb.c:2454:26: warning: unused variable 'mclist' [-Wunused-variable]
2つあるみたいだけど、先の方(390行目)をチェックしてみると、struct net_device_ops に ndo_set_multicast_list というメンバがないみたいなんだよね。

そこらに落ちてる 2.6.32 のヘッダ3.2のヘッダを見比べてみると、ほんとうにそのメンバだけなくなっている。何が代替だか自明でなさそうなので、とりあえず消しちゃうことにする。

@@ -387,7 +387,9 @@
     .ndo_stop        = device_close,
     .ndo_get_stats        = device_get_stats,
     .ndo_start_xmit        = device_xmit,
+#ifdef HAVE_MULTICAST
     .ndo_set_multicast_list    = device_set_multi,
+#endif
     .ndo_do_ioctl        = device_ioctl,
 };
 #endif

すると、他の警告がいっぱい表示されながらもビルドに成功して vntwusb.ko ができた。

試すのはまた明日移行にしようかな。遅いし。

2013-08-06

そもそもカーネルモジュールのビルドしかた

https://www.kernel.org/doc/Documentation/kbuild/ あたりを読むべきらしい。
ぐぐったら modules.txt が引っかかったが、これだけ読んでも、どうも kbuild という機構がわからないと壊れたMakefileをなおせるようにならなさそうだ。

とりあえず、何もしないモジュールを作ってみる例がある。
http://wiki.bit-hive.com/tomizoo/pg/Loadable%20Kernel%20Module%A4%CE%BA%EE%A4%EA%CA%FD

これを最新のカーネルバージョンで試してみるというのも一法だろう。

2013-08-04

VIA VNT6656 USB Wifi Module を Ubuntu からまだ使えていないメモ

まあ表題のとおりなわけでダメなんだけど、ダメなりにメモを残しておこう。

工人舎MLというネットブックを持っていて、金物は元気なんだけどWindows XPだからそろそろ延命策を考えたいところ。とりあえず、楽そうなところでUbuntu 12.04 LTS を入れたらさくっと動いたのでそこはよし。Tipsがあるとすれば、BIOSではブータブルUSBはHDD扱いされるということかな。

で、内蔵無線LANがVIA VNT6656なんだけど、これがどうも始末の悪いものであるらしい。

http://www.linuxforums.org/forum/suse-linux/147396-install-via-vnt6656-wireless-usb.html

最後を見ると、ありがたくもVIAがドライバを出してくれてはいるのだけれど、これが古い。

http://www.viaembedded.com/en/products/boards/1890/1/VNT6656_USB_Module_/_Dongle.html

Ubunto 11.04 まで対応なんだけどね。うーんちょっとサポート切れバージョンに戻すのも心配だよね。もともとXP移行なんで、なにやってるかわからない。

まず、インストラクションにのっとって unzip; make clean; make を試みると、 driver/Makefileが爆死。

$ unzip VT6656_Linux_src_v1.21.03_x86_11_04.zip
$ cd VT6656_Linux_src_v1.21.03_x86/
$ make
...
Makefile:116: *** Linux kernel source not configured - missing config.h.  Stop.
これは、最近の Linux ではカーネルソースに linux/config.h がなくなったからであるらしいので、ないものは作ればよい。作り方はこれでいいかは知らんが Makefile は黙る...
 $ sudo touch /lib/modules/3.2.0-51-generic-pae/build/include/linux/config.h

...かとおもったらそうでもない。
$ make
...
gcc    -c -o main_usb.o main_usb.c
In file included from main_usb.c:50:0:
device.h:40:24: fatal error: linux/init.h: No such file or directory
compilation terminated.
make[1]: *** [main_usb.o] Error 1
 あせったけれど、よくよくコマンドラインをみるとヘッダの場所を教えていないのでコンパイルできるわけがない。それはなぜかと make -p の結果を読んだりしてみると、どうやら Makefile 内の .c.o ルールが使われていないみたい。

対症療法だけど、システムの %.o: %.c ルールに然るべきコンパイラオプションを渡すには、 無視されてしまう EXTRA_CFLAGS 変数の代わりに CFLAGS に同じことを設定すればいい。で、その設定らしきものが既に Makefile にコメントで入っているという中途半端な状態。

とりあえず、こうするとヘッダが見つけられるようにはなる。

$ diff -ru VT6656_Linux_src_v1.21.03_x86 work-vt6656/
diff -ru VT6656_Linux_src_v1.21.03_x86/driver/Makefile work-vt6656/driver/Makefile
--- VT6656_Linux_src_v1.21.03_x86/driver/Makefile    2009-09-07 09:53:36.000000000 +0900
+++ work-vt6656/driver/Makefile    2013-08-04 23:05:11.296911687 +0900
@@ -62,12 +62,13 @@


 ifeq ($(HOSTAP), 1)
-#  CFLAGS += -DHOSTAP
+  CFLAGS += -DHOSTAP
   EXTRA_CFLAGS += -DHOSTAP
 endif


-#CFLAGS += -I$(PWD) -I$(PWD)/../include -I$(PWD)/include
+CFLAGS += -I$(PWD) -I$(PWD)/../include -I$(PWD)/include -I$(KSRC)/include \
+    -I$(KSRC)/arch/x86/include
 EXTRA_CFLAGS += -I$(PWD) -I$(PWD)/../include -I$(PWD)/include

 # build rule
@@ -113,7 +114,7 @@
 endif

 ifeq (,$(wildcard $(CONFIG_FILE)))
-  $(error Linux kernel source not configured - missing config.h)
+  $(error Linux kernel source not configured - missing config.h in $(KSRC))
 endif

 ifneq (,$(findstring egcs-2.91.66, $(shell cat /proc/version)))
@@ -126,10 +127,10 @@
 CC := $(foreach cc, $(CC), $(test_cc))
 CC := $(firstword $(CC))

-#CFLAGS += -Wall -DLINUX -D__KERNEL__ -DMODULE  -DEXPORT_SYMTAB -D__NO_VERSION__ -O2 -pipe
-#CFLAGS += -I$(KSRC)/include -Wstrict-prototypes -fomit-frame-pointer -fno-strict-aliasing
-#CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \
-#            echo "-DMODVERSIONS -include $(KSRC)/include/linux/modversions.h")
+CFLAGS += -Wall -DLINUX -D__KERNEL__ -DMODULE  -DEXPORT_SYMTAB -D__NO_VERSION__ -O2 -pipe
+CFLAGS += -I$(KSRC)/include -Wstrict-prototypes -fomit-frame-pointer -fno-strict-aliasing
+CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \
+            echo "-DMODVERSIONS -include $(KSRC)/include/linux/modversions.h")
 EXTRA_CFLAGS += -Wall -DLINUX -D__KERNEL__ -DMODULE  -DEXPORT_SYMTAB -D__NO_VERSION__ -O2 -pipe
 EXTRA_CFLAGS += -I$(KSRC)/include -Wstrict-prototypes -fomit-frame-pointer -fno-strict-aliasing
 EXTRA_CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \
Only in work-vt6656/: make.log
Only in work-vt6656/: utility

で、現状、 カーネルソースヘッダの arch/x86/include/asm/arch_hweight.h:53:7 でexpected ‘:’ or ‘)’ before ‘POPCNT64’ と言われて止まる。

このへんはアセンブリなので正直分からないのだけれど、構文エラーということは、おそらくはマクロの未定義とかなんとか、正しいヘッダの読み方をしていないからだろう。

が、しかし、それが何なのかはわからない。