이번에 s5pv210 안드로이드에 Marvell sd8787 wlan모듈을 기존 리눅스 방식대로 올려보았습니다.

일단 커널 콘솔모드에서만 동작하도록 하는 것이 목표였기 때문에 기존 리눅스 방식대로 따라했습니다.


맨처럼 sd8787 무선랜 모듈 드라이버를 빌드해서 .ko를 생성합니다.

반드시 커널 오브젝트 파일들이 있는 빌드 디렉토리를 알아야하기 때문에 해당 안드로이드 커널 소스도 준비해야합니다.

그리고 반드시 kernel menuconfig에서 아래와 같이 IEEE 802.11 Host AP 및 Marvell Libertas support를 활성화 시켜서 빌드합니다.

$ ./make-s5pv210.sh menuconfig


Device Drivers ---> [*] Network device support ---> [*] Wireless LAN --->

<*> Marvell 8xxx Libertas WLAN driver support with thin firmware
<*> IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP) 
<*> Marvell 8xxx Libertas WLAN driver support


해당 메뉴가 나오지 않으면 아래의 경로에서 옵션을 추가한 후 그 위치로 가보시면 메뉴가 세로 생성되어 있습니다.


[*] Networking support ---> -*- Wireless --->


<*>   cfg80211 - wireless configuration API

[*]     cfg80211 regulatory debugging 

 [*]     enable powersave by default 

 [*]     cfg80211 wireless extensions compatibility 

[*]   Wireless extensions sysfs files 

 -*-   Common routines for IEEE802.11 drivers 

 <*>   Generic IEEE 802.11 Networking Stack (mac80211)  

 [*]   Minstrel  


드라이버 소스 디렉토리의 Makefile을 열기한 후 다음과 같이 수정합니다. Makefile은 소스(src/)디렉토리에 있습니다.

아래처럼 방금 위에서 수행했던 커널의 빌드 디렉토리를 지정합니다.

root@xxx:src#vi Makefile

 KERNELDIR ?=../../../../../../kernel/build_linux-2.6.35.14   

그리고 툴체인도 안드로이드 커널을 빌드했던 동일한 CodeSourcery 툴체인을 지정합니다.

CROSS_COMPILE ?=  arm-none-eabi-



이제 빌드를 합니다. 빌드는 반드시 root 계정으로 합니다. root가 아니면 빌드가 되지 않습니다.

소스 디렉토리에서 간단히 make만 하면 빌드가 됩니다. 그전에 clean을 한번 하고 make하는 것이 좋습니다.


root@xxx:src# make clean

root@xxx:src# make


끝나고 나면 아래와 같이 2개의 모듈이 생겼다는 메시지가 표시됩니다. 그리고 ls -al해보면 mlan.ko와 sd8787.ko파일이

생성되어 있습니다.

.............

  Building modules, stage 2.

  MODPOST 2 modules

  CC      /driver-sdio-wlan-AW_NH387L/src/mlan.mod.o

  LD [M] /driver-sdio-wlan-AW_NH387L/src/mlan.ko

  CC      /driver-sdio-wlan-AW_NH387L/src/sd8787.mod.o

  LD [M]  /driver-sdio-wlan-AW_NH387L/src/sd8787.ko

make[1]: Leaving directory `/kernel/build_linux-2.6.35.14'

그리고 중요한 sd8787의 펌웨어 바이너리도 챙겨 놓습니다. 펌웨어는 hotplug 디렉토리에 있습니다.
root@xxx:src# cd hotplug/firmware/mrvl/
root@xxx:mrvl# ls
sd8787_uapsta.bin  sd8787_uapsta_w1.bin
root@xxx:mrvl#

이제 위에서 생성한 .ko파일들과 펌웨어 바이너리 파일들을 안드로이드 루트파일 시스템으로 옮깁니다.

그런데 안드로이드 파일시스템이 기존 리눅스와 달라서 모듈 위치와 hotplug 펌웨어 위치를 찾는것이 애매했습니다.

모듈들은 nfs로 mount해서 설치해도 되지만 펌웨어 바이너리는 특정디렉토리에 넣어야 찾아서 다운로드되고 무선랜 장치가 active 됩니다.


이래저래 찾아보니 안드로이드에서는 .ko 모듈들을 /system/lib/modules 아래에 넣고 

hotplug 펌웨어는 보통 /system/etc/firmware 디렉토리에 위치합니다. 

커널마다 다르긴 한데 /system 디렉토리 밑에 firmware라는 디렉토리가 있으면 거기에 무선랜의 펌웨어를 올리면 됩니다.


저같은 경우는 이더넷을 이용해서 nfs를 mount해서 아래와 같은 경로에 모듈과 펌웨어를 넣었습니다. 

안드로이드 콘솔에서 busybox를 이용해서 ifconfig로 유선랜을 활성화하고 mount로 nfs를 마운트합니다.

그전에 su로 root 계정으로 만들어야 합니다. 자동완성이 되지 않기 때문에 tab을 누리지 않도록 합니다..^^:;;;

$ su

sh: can't access tty; job control turned off

# busybox ifconfig eth0 192.168.1.10

# busybox mount -t nfs -o nolock 192.168.1.2:/nfs /mnt/nfs

# cd /mnt/nfs

# ls

mlan.ko

sd8787.ko

sd8787_uapsta.bin

sd8787_uapsta_w1.bin

#busybox cp -a *.bin /system/etc/firmware/mrvl

#busybox cp -a *.ko /system/modules

이렇게 한 후에 insmod로 모듈을 설치합니다.

# cd /system/modules

# insmod mlan.ko

# insmod sd8787.ko

[  330.542032] WLAN FW is active

#

이렇게 나오면 정상적으로 펌웨어가 다운로드 되어서 모듈이 활성화 되었고 iwconfig로 확인 가능합니다.

# iwconfig

lo        no wireless extensions.


eth0      no wireless extensions.


ifb0      no wireless extensions.


ifb1      no wireless extensions.


usb0      no wireless extensions.


sit0      no wireless extensions.


ip6tnl0   no wireless extensions.


mlan0     IEEE 802.11-DS  ESSID:""  Nickname:""

          Mode:Managed  Access Point: Not-Associated   Bit Rate:1 Mb/s

          Tx-Power=8 dBm

          Retry limit:9   RTS thr=2347 B   Fragment thr=2346 B

          Encryption key:off

          Power Management:on

          Link Quality=0/5  Signal level=0 dBm  Noise level=0 dBm

          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:1

          Tx excessive retries:0  Invalid misc:0   Missed beacon:0


uap0      IEEE 802.11-DS  ESSID:""

          Mode:Master  Frequency:2.437 GHz  Access Point: Not-Associated

          Encryption key:off

          Link Quality:0  Signal level:0  Noise level:0

          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0

          Tx excessive retries:0  Invalid misc:0   Missed beacon:0


#

이렇게 해서 무선랜을 AP와 붙이기 위해서는 리눅스와 마찬가지로 wireless tools를 사용하시면 됩니다.

아래는 WPA 방식으로 AP와 연결하기 위한 예입니다.

# iwpriv mlan0 passphrase "1;passphrase=12345abcd"           

# iwconfig mlan0 essid "mlan_ap"                                     

# ifconfig mlan0 192.xxx.xxx.xxx  또는 udhcpc -I mlan0

아니면 안드로이드에 기본 내장된 wpa_supplicant를 이용해서 연결할수도 있습니다. 이 경우 etc/wifi/wpa_supplicant.conf파일을 수정해서 적용합니다. 마찬가지로 WPA/TKIP 방식으로 AP와 연결합니다. 아무래도 WPA로 접속할 경우 wpa_supplicant가 더욱 편할 것 같습니다.

##### wpa_supplicant configuration file template #####

network={

        ssid="mlan_ap"

        proto=WPA

        key_mgmt=WPA-PSK

        pairwise=TKIP

        group=TKIP

        psk="12345abcd"

}

이렇게 wpa_supplicant.conf를 수정한 후에 다음과 같이 무선랜을 연결합니다. wpa_supplicant가 데몬형태로 실행되기 때문에 반드시 끝에 &를 붙여서 백그라운드로 수행하셔야 합니다.
# wpa_supplicant -Dwext -imlan0 -c/etc/wifi/wpa_supplicant.conf &
# [ 1331.979050] ADDRCONF(NETDEV_UP): mlan0: link is not ready
# [ 1334.341040] ADDRCONF(NETDEV_CHANGE): mlan0: link becomes ready
# ifconfig mlan0 192.xxx.xxx.xxx  또는 udhcpc -I mlan0


아래처럼 그냥 wpa_supplicant만 입력하셔도 example이 나오는데 거기서 약간 수정하셔도 됩니다.
# wpa_supplicant
wpa_supplicant v0.6.10
Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> and contributors
......
usage:
  wpa_supplicant [-BddhKLqqtuvW] [-P<pid file>] [-g<global ctrl>] \
        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
        [-b<br_ifname>] [-f<debug file>] \
        [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
        [-p<driver_param>] [-b<br_ifname>] ...]
.......
  -N = start describing new interface
example:
  wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant.conf
#

감사합니다.