into the void

ソフトウェアに関する雑多な調査日記

Androidを載せたbeagleboard-xmをWiFi APにするまで(其の伍)

今日はzd1211のドライバとwireless-toolsをbeagleboard-xm上のfroyo用にコンパイルしてみる。
wireless-toolsはiwconfigコマンドを使いたいので入れる。
zd1211はドライバなのでいつも通りの方法でクロスコンパイルしてみる。wireless-toolsはユーザランドのプログラムなのでandroidのビルドシステム(Android.mkとmmコマンド)を使ってビルドしてみる。
とりあえずWiFiモジュールがAPモードで動いたらしいところまで。DHCPサーバとDNSリレーサーバのポーティングはまた別の日に。
今回参考にしたページは下記。
http://d.hatena.ne.jp/h_kojima/20110617/1308324429

kernel

WiFiドライバをmakeする前にLinuxカーネルのwireless extensionに関するconfigurationを変更してmakeする。
具体的には、kernelソースの中のnet/wireless/Kconfigを下記のように修正した後で、make menuconfigでwireless extensionに関する設定をONにして、makeする。

$ diff Kconfig Kconfig.org 
2c2
< 	bool "WIRELESS_EXT"
---
> 	bool
17c17
< 	bool "WIRELESS_PRIV"
---
> 	bool
cd kernel/net/wireless
cp Kconfig Kconfig.org(念のためバックアップ)
vi Kconfig(上記のdiffのようにKconfigを修正する)
make ARCH=arm CROSS_COMPILE=<top-dir>/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- menuconfig
make ARCH=arm CROSS_COMPILE=<top-dir>/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- uImage

makeが終わるとuImageが/kernel/arch/arm/boot/uImageにできる。

zd1211

kernelのビルドが終わった後でドライバをビルドする。基本的にはUbuntu上でビルドしたときと同じ手順で、クロスコンパイル用の設定追加を行う。
http://d.hatena.ne.jp/samehada_shiro/20111229/1325149643
つまり、ソースとパッチをダウンロードしてきて、それぞれ展開して、パッチを12番まであてて、makeする。
ロスコンパイル用の設定はar2524drvフォルダのMakefileを下記のように書き換えることで行う。
環境変数ARCHとCROSS_COMPILEを新たに定義して、HOSTとKDIRとKERN_26とKERNEL_SOURCEについては値を書き換える。
で、makeのオプションにARCHとCROSS_COMPILEを足す。
※$(TOPDIR)はandroidソースツリーのトップディレクトリに読み替えてください。

6,7d5
< ARCH=arm
< CROSS_COMPILE=$(TOPDIR)/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
9c7
< HOST=$(TOPDIR)/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
---
> HOST=
12,14c10,11
< #KERN_VER=$(shell uname -r | cut -b1-3;)
< #KDIR := /lib/modules/$(shell uname -r)/build
< KDIR := $(TOPDIR)/kernel
---
> KERN_VER=$(shell uname -r | cut -b1-3;)
> KDIR := /lib/modules/$(shell uname -r)/build
21,27c18,24
< #ifeq ($(KERN_VER), 2.6) 
< KERN_26=y
< KERNEL_SOURCE=$(TOPDIR)/kernel
< #else 
< #    KERN_24=y
< #    KERNEL_SOURCE=/usr/src/linux-2.4
< #endif
---
> ifeq ($(KERN_VER), 2.6) 
>     KERN_26=y
>     KERNEL_SOURCE=/usr/src/linux-2.6.9
> else 
>     KERN_24=y
>     KERNEL_SOURCE=/usr/src/linux-2.4
> endif
356c353
< 		$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
---
> 		$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

ビルドできたらarm用のバイナリができていることを確認する。

$ file zd1211b.ko 
zd1211b.ko: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped

wireless-tools

次はドライバを操作するためのiwconfig等のコマンドを使えるようにするためにwireless-toolsをポーティングする。
最初はwireless-tools本家からソースを持ってきてandroid用にmake環境を作ろうと思っていたがなかなかうまくいかなかったので、いろいろ探していたらテザリングアプリのサイトからandroid用にポーティングされたwireless-toolsを見つけたので、それを使うことにした。
手順は下記のような感じ。svnからソースをcheckoutして、androidのexternalディレクトリにコピーして、mmでmakeする。
1. svnでチェックアウトしてexternelディレクトリにコピー。

svn checkout http://android-wifi-tether.googlecode.com/svn/tools/wireless-tools android-tether-wireless-tools
mkdir $(top-dir)/external/wireless-tools
cp android-tether-wireless-tools/* $(top-dir)/externel/wireless-tools
rm $(top-dir)/external/wireless-tools/.svn (svnフォルダはいらないので削除)

2. androidビルド用の環境設定。envsetup.shをインクルードで実行。TARGET_PRODUCT環境変数の設定。

cd $(top-dir)
. build/envsetup.sh
export TARGET_PRODUCT=beagleboard

3. mmでビルド。

cd $(top-dir)/external/wireless-tools
mm

4. ビルドできたか確認。iwconfigとかが生成されていればOK。

ls ../../out/target/product/beagleboard/system/bin/iw*
../../out/target/product/beagleboard/system/bin/iwconfig
../../out/target/product/beagleboard/system/bin/iwevent
../../out/target/product/beagleboard/system/bin/iwgetid
../../out/target/product/beagleboard/system/bin/iwlist
../../out/target/product/beagleboard/system/bin/iwpriv
../../out/target/product/beagleboard/system/bin/iwspy

動かしてみる

できあがったuImage、zd1211b.ko、iwconfigなどをbeagleboard-xmのSDカードに書き込む。
uImageはbootパーティションに、zd1211bはsystemパーティションの/system/lib/modulesに、iwconfigなどのコマンドは/system/binにコピーする。コピーした後はsyncしてumountを忘れずに。
SDカードにコピーできたらbeagleboard-xmに差し込んで起動。無事起動したら、ドライバをinsmodして、USB無線LANモジュールを差し込んで、iwconfigで設定する。

# insmod /system/lib/modules/zd1211b.ko                                         
                                                                                
 _____     ____    _    ____                                                    
|__  /   _|  _ \  / \  / ___|                                                   
  / / | | | | | |/ _ \ \___ \                                                   
 / /| |_| | |_| / ___ \ ___) |                                                  
/____\__, |____/_/   \_\____/                                                   
     |___/                                                                      
ZD1211B - version 3.0.0.56                                                      
usbcore: registered new interface driver zd1211b    

みなれたロゴがでてきた。insmod成功。モジュール差し込む。

usb 1-2.4: new high speed USB device using ehci-omap and address 6            
vendor_id = 2019                                                                
product_id = 5303                                                               
USB 2.0 Host                                                                    
Release Ver = 4810                                                              
EEPORM Ver = 4810                                                               
Finsih download Firmware. Ready to reboot                                       
PA type: 0                                                                      
PHYNEWLayout = 1                                                                
AiroHa AL2230RF                                                                 
AllowedChannel = 00013fff                                                       
Region:73          
# netcfg                                                                        
lo       UP    127.0.0.1       255.0.0.0       0x00000049                       
usb0     UP    192.168.1.14    255.255.255.0   0x00001043                       
ath0     DOWN  0.0.0.0         0.0.0.0         0x00001002  

うまく認識したっぽい。インタフェースもできてる。Ubuntuのときとちがってこの段階ではまだモジュールのLEDは点灯しない。
この後、iwconfigで設定するがその前にnetcfgでインタフェースをupしておく。するとモジュールのLEDがつく。upするまえにiwconfigを実行しても下記のように失敗する。

# iwconfig ath0 mode "Master"                                                   
Error for wireless request "Set Mode" (8B06) :                                  
    SET failed on device ath0 ; Invalid argument.     

iwconfigでUbuntのときと同じように設定する。

netcfg ath0 up
iwconfig ath0 mode Master
iwconfig ath0 essid fragile
iwconfig ath0 channel 6
iwconfig ath0 rate 11M
iwconfig ath0 key 1111111111

Macbook Airからちゃんとessidがサーチできて、つなぎにいけることを確認した。DHCPサーバ等いれてないのでIPでの通信確認はまだ。(とりえあず静的IPでやってみてもいいかも)

modversoinsについて

ドライバのロード時にmodversionsではまったのでメモ書き。
作ったドライバをinsmodしたときに「disagrees about version of symbol dev_alloc_skb」とかがでてインストールできないことがあった。
原因はカーネルの新しくビルドしたバージョンに入れ替えるのを忘れていたため。
カーネルモジュールはinsmodするときに、カーネルとの互換性チェックのためにmodversionsという仕組みでチェックを行うらしい。
カーネルビルド時にシンボルの一つ一つについてチェックサム的なものが生成され、保存される。それはカーネルのソースディレクトリにあるModule.sysversファイルで確認できる。で、モジュールのビルド時にこの情報が参照されてモジュール側にも記録される。これはmodprobe --dump-modversionsで確認できる。
で、insmodするときにカーネル側とモジュール側のチェックサムの情報がすべて一致するかどうかチェックされるという具合。一致しないものがあると上記の「disagrees about...」というエラーがでてインストールさせてくれない。
詳しくは下記のサイト。
http://d.hatena.ne.jp/enakai00/20110509/1304910773
今回はカーネル側のModule.sysversとモジュール側のmodprobeでの出力結果を比べても同一なのでおかしいなーと思っていたら、そういえばカーネル入れ替えてなかったかもと気づいた。。。。ビルドしてから実際動かしてみるまで結構日にちがたっていたのでカーネルも書き換えていたことを忘れていた。