Ralink 측으로부터 샘플로 받은 One-Chip 기반의 USB-to-Wireless Dongle 인 RT3572 에 대한 포팅 및 테스트 방법을 소개한다.
RT3572 의 경우, Ralink 에서 아직 시장에 출시한 제품이 아니기 때문에 WLB5254USB 와 같이 리눅스 커널에서 기본적으로 지원되지 않는다.
따라서 Ralink 로 부터 디바이스 드라이버 코드를 받아 컴파일하여 현재 커널에 올리는 방법을 사용했다.
참고로 개발환경은 다음과 같다.

H/W Saturn 6
S/W GP1 (linux-2.6.26)

타겟(DTV)에 올리기 전에, PC 기반의 윈도우, 리눅스 상에서 동작하는 것을 확인하였다. 윈도우용 드라이버는 http://www.ralinktech.com/ralink/Home/Support/Windows.html 에서 다운로드 할 수 있다.

디바이스 드라이버 컴파일하기

리눅스용 드라이버(2009_0226_RT3572_Linux_STA_v2.1.0.0.tar.bz2)의 경우, 공개되어 있지 않아, Ralink 측으로부터 받았다.
PC 기반으로 컴파일하기 위해서는 별다른 수정없이 컴파일하면 된다. 하지만, 타겟에 올리기 위해서는 Makefile 을 수정해야 한다.

#cd 2009_0226_RT3572_Linux_STA_v2.1.0.0
#vi Makefile
...
RT28xx_MODE = STA
TARGET = LINUX
CHIPSET = 3572
...
PLATFORM = STAR
...
ifeq ($(PLATFORM), STAR)
LINUX_SRC = /vol/users/wjkim/work/gp/os/saturn6_linux/kernel/linux-2.6.26-saturn6
CROSS_COMPILE = /opt/crosstool/mipsel-gcc-4.1.2-uclibc-0.9.28.3-mips32/bin/mipsel-linux-
endif
...

RT3572 디바이스 드라이버에서는 RT2870STA.dat 파일이다. 이 파일은 profile 과 같은 역할을 한다. 설정 파일이라고 보면 되겠다. 이 파일은 open() 할때('ifconfig ra0 up' 실행 시) 디바이스 드라이버에서 읽어들인다.
따라서 이 파일이 없다면, 아래와 같은 에러가 발생한다.

#ifconfig ra0 up
ifconfig: ioctl 0x8914 failed: Operation not permitted

.dat 파일의 경로는 /include/os/rt_linux.h 에서 지정할 수 있다.

...
#ifdef RTMP_MAC_USB
#define STA_PROFILE_PATH			"./RT2870STA.dat"     // rt3572sta.ko 파일과 같은 디렉토리에 있다고 가정한다
#define STA_DRIVER_VERSION			"2.1.0.0"
#ifdef MULTIPLE_CARD_SUPPORT
#define CARD_INFO_PATH			"/etc/Wireless/RT2870STA/RT2870STACard.dat"
#endif // MULTIPLE_CARD_SUPPORT //
#endif // RTMP_MAC_USB //
...

주석에서도 설명했듯이, 나중에 .ko 파일과 .dat 파일을 rootfs 에 넣을 때, 같은 디렉토리에 복사해야 한다.
이제는 RT2870STA.dat 파일을 살펴보자!

#The word of "Default" must not be removed
Default
CountryRegion=5
CountryRegionABand=7
CountryCode=
ChannelGeography=1
SSID=LGEWEP
NetworkType=Infra
WirelessMode=5
Channel=0
AuthMode=WEPAUTO
EncrypType=WEP
DefaultKeyID=1
Key1Type=0
Key1Str=a1215a0824b0501b1009c0522d
PSMode=CAM

위의 설정은 사내 무선 AP 망에 WEP 인증방식으로 접속할 경우를 기준으로 작성하였다. 자세한 설정 방법은 README_STA 파일을 참고하기 바란다.
'ifconfig ra0 up' 을 실행함으로서, 위의 설정으로 세팅이 되더라도, 나중에, 'iwpriv' 명령어를 이용해서 바꿀 수 있다.

여기서 잠시 아주 중요한 이야기를 해야 겠다. 앞에서 설명한 Makefile 파일만 수정하면, 컴파일하여 .ko 파일을 생성하는 데는 아무런 문제가 없다. 하지만, 타겟에 올리고 모듈을 올리는 과정 또는 올리고 나서 'ifconfig ra0 up' 명령 시에 Segmentation Fault 가 발생하는 문제가 있었다. 증상은 다음과 같다.

#insmod rt3572sta.ko
#lsmod
Module                  Size  Used by    Tainted: P
rt3572sta             502336  -
...
#ifconfig ra0 up
Segmentation fault

이때, 에러 로그는 다음과 같다.

<1>[   68.485000] CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == c06762fc, ra == c06762f4
<4>[   68.485000] Oops[#1]:
<4>[   68.485000] Cpu 0
<4>[   68.485000] $ 0   : 00000000 10008c00 00000000 35720220
<4>[   68.485000] $ 4   : 00000004 808bd800 85c40280 805cc6c4
<4>[   68.485000] $ 8   : 867fbfe0 00008c00 00000000 86796000
<4>[   68.485000] $12   : 807d0bc8 86784d08 3b9aca00 00000000
<4>[   68.485000] $16   : 00000000 c0580000 c0580000 c067e00c
<4>[   68.485000] $20   : c0683800 00008914 85c3310c 867fbe10
<4>[   68.485000] $24   : 807d0b58 807d0bc8
<4>[   68.485000] $28   : 867fa000 867fbd00 00000000 c06762f4
<4>[   68.485000] Hi    : 00000000
<4>[   68.485000] Lo    : 3b9aca00
<4>[   68.485000] epc   : c06762fc RTUSBReadMACRegister+0x4c/0x78 [rt3572sta]
Tainted: P
<4>[   68.485000] ra    : c06762f4 RTUSBReadMACRegister+0x44/0x78 [rt3572sta]
<4>[   68.485000] Status: 10008c03    KERNEL EXL IE
<4>[   68.485000] Cause : 0080000c
<4>[   68.485000] BadVA : 00000000
<4>[   68.485000] PrId  : 0001906c (MIPS 4KEc)
<4>[   68.485000] Modules linked in: rt3572sta mdrv_ve(P) mdrv_vd(P) mdrv_ttx(P) mdrv_tsp(P) mdrv_spi(P) mdrv_scaler(P) mdrv_rld(P) mdrv_pwm(P) 
<4>[   68.485000] Process ifconfig (pid: 943, threadinfo=867fa000, task=85c29160, tls=00000000)
<4>[   68.485000] Stack : 00000000 c0580000 c06613ec c06762b0 c0631ee0 00001000 867fbd20 00000004
<4>[   68.485000]         35720220 00001002 c06349ec c0634998 ffffffea 0000540d 86c65400 86dfe500
<4>[   68.485000]         7feef5e8 86c65410 35720220 004376c8 c0580000 867dcc00 00001043 00001002
<4>[   68.485000]         00000000 c0663a70 000fa1a4 00000000 000000e1 85c278f0 8081c6a0 8045cb44
<4>[   68.485000]         c0580000 c0663bec 80795210 86dfe500 0000540d 8081c7a0 867dcc00 00000000
<4>[   68.485000]         ...
<4>[   68.485000] Call Trace:
<4>[   68.485000] [<c06762fc>] RTUSBReadMACRegister+0x4c/0x78 [rt3572sta]  // 마지막 Segmentation fault 가 발생하는 지점이다
<4>[   68.485000] [<c0634998>] rt28xx_init+0x68/0x3d4 [rt3572sta]
<4>[   68.485000] [<c0663a70>] rt28xx_open+0x4c/0xe4 [rt3572sta]
<4>[   68.485000] [<c0663bec>] MainVirtualIF_open+0xe4/0x10c [rt3572sta]
<4>[   68.485000] [<806052b8>] dev_open+0x7c/0x124
<4>[   68.485000] [<80605ccc>] dev_change_flags+0x9c/0x1f8
<4>[   68.485000] [<8064d59c>] devinet_ioctl+0x7ec/0x880
<4>[   68.485000] [<8064fa2c>] inet_ioctl+0xc0/0xd8
<4>[   68.485000] [<805f486c>] sock_ioctl+0x210/0x2c0
<4>[   68.485000] [<80499410>] vfs_ioctl+0xc0/0xd8
<4>[   68.485000] [<804994d0>] do_vfs_ioctl+0xa8/0x3e8
<4>[   68.485000] [<80499860>] sys_ioctl+0x50/0x90
<4>[   68.485000] [<8040bad0>] stack_done+0x20/0x3c
<4>[   68.485000]
<4>[   68.485000]
<4>[   68.485000] Code: afa00010  04400006  8fa30020 <ae030000> 8fbf002c  8fb00028  03e00008  27bd0030  2403ffff

Segmentation fault 가 발생하는 RTUSBReadMACRegister() 함수를 보면, #ifdef 구문이 있는 H/W 의존적인 코드들이 대부분이다. 문제의 원인은 Saturn6 H/W 스펙에 디바이스 드라이버 코드가 적절히 대응되지 못하는 것이라 짐작했다.
조금 뒷 이야기를 하자면, 나는 Makefile 에 지정되어 있는 Platform 을 일일이 바꿔가며 테스트를 했었다. 하지만, 결과는 동일했다.
결국 ralink 측 엔지니어의 도움을 받아 문제를 해결할 수 있었다.

지금부터 잘 보기 바란다. 아래와 같이 config.mk 파일을 주석에 따라 수정한다.

#cd os/linux
#vi config.mk
...
WFLAGS := -DAGGREGATION_SUPPROT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX -Wall -Wstrict-prototypes -Wno-trigraphs    // -DDBG 삭제한다
...
Ifeq ($(RT28xx_MODE), STA)
WFLAGS += -DCONFIG_STA_SUPPORT        // -DDBG 삭제한다
...
ifeq ($(CHIPSET), 3572)
WFLAGS +=-DRTMP_MAC_USB -DRTMP_USB_SUPPORT -DRT2870 -DRT30xx -DRT35xx -DRTMP_TIMER_TASK_SUPPORT -DRTMP_RF_RW_SUPPORT -DRTMP_EFUSE_SUPPORT -DST    // ★☆ 아주 중요하다 ★☆
endif
...
ifeq ($(PLATFORM), STAR)
#CFLAGS := ...                  // 주석 처리한다
EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include
endif
...

문제의 핵심은 '-DST' 였다. 이것을 define 해 줌으로서, 현재의 Saturn6 H/W 스펙에 충족할 수 있었다.
이제 다시 컴파일 하여 테스트 보자.

/mnt/lg/lgapp/drivers/wireless_util # insmod rt3572sta.ko
[   81.807000] rtusb init --->, Jit=326
[   81.829000] usbcore: registered new interface driver rt2870
/mnt/lg/lgapp/drivers/wireless_util # lsmod
Module                  Size  Used by    Tainted: P
rt3572sta             502848  -
...
/mnt/lg/lgapp/drivers/wireless_util # ifconfig ra0 up
[   52.377000] 0x1300 = 00064300
/mnt/lg/lgapp/drivers/wireless_util # ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
 
ra0       Link encap:Ethernet  HWaddr 00:0C:43:32:41:2A
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1374 errors:1 dropped:0 overruns:0 frame:0
          TX packets:87 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:240795 (235.1 KiB)  TX bytes:6832 (6.6 KiB)

여기서는 사내 무선 AP 에 접속하여, IP 를 받아온 후에 외부와의 네트워킹이 가능한지 확인해보겠다.
앞서 'dat 파일 만들기' 에서 설명했듯이, 추가적인 별다른 설정이 필요없다. 단지 udhcpc 를 이용해서 IP 를 받아오기만 하면 된다.
udhcpc 에 대한 자세한 설정사항은 [“WLB5254USB 사용하기”] 를 참고하기 바란다.

#ifconfig ra0 up    // 자동으로 RT2870STA.dat 파일을 읽어들임으로서, AP 에 WEP 인증을 사용하여 연결하는 설정이 완료되었다
#busybox udhcpc -i wlan0 -s simple.script renew
### adapter index 2
### adapter hardware address 00:0c:43:32:41:2a
udhcpc (v1.10.1) started
### vfork'ing and execle'ing ../../../user/simple.script
### entering raw listen mode
### opening raw socket on ifindex 2
### got raw socket fd 23
### attached filter to raw socket fd 23
### bound to raw socket fd 23
### adding option 0x35
### adding option 0x3d
### adding option 0x3c
### adding option 0x39
Sending discover...
### Waiting on select...
### adding option 0x35
### adding option 0x3d
### adding option 0x3c
### adding option 0x39
Sending discover...
### Waiting on select...
### Got valid DHCP packet
### adding option 0x35
### adding option 0x3d
### adding option 0x3c
### adding option 0x32
### adding option 0x36
Sending select for 10.177.188.37...
### Waiting on select...
### Got valid DHCP packet
Lease of 10.177.188.37 obtained, lease time 691200
### vfork'ing and execle'ing ../../../user/simple.script
deleting routers
route: ioctl 0x890c failed: No such process
adding dns 156.147.135.180
adding dns 156.147.135.181
adding dns 165.244.106.110
### entering none listen mode
/mnt/lg/lgapp/drivers/wireless_util # ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
 
ra0       Link encap:Ethernet  HWaddr 00:0C:43:32:41:2A
          inet addr:10.177.188.37  Bcast:10.177.189.255  Mask:255.255.254.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:14310 errors:7 dropped:0 overruns:0 frame:0
          TX packets:114 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2623959 (2.5 MiB)  TX bytes:9910 (9.6 KiB)
/mnt/lg/lgapp/drivers/wireless_util # telnet 211.196.153.28
 
Entering character mode
Escape character is '^]'.
 
login:

각 인증 방식에 따라 각각 설정을 달리해주어야 한다. iwpriv 명령어를 사용해서 다음과 같이 스크립트 파일을 만들어서 손쉽게 설정할 수 있다.
2009_0302_rt2870_linux_sta_v2.1.0.0_releasenote_dpb_2009_0318.pdf 를 참고하기 바란다.

#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set NetworkType=Infra
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set AuthMode=OPEN
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set EncrypType=NONE
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set NetworkType=Infra
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set AuthMode=WPAPSK
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set EncrypType=TKIP
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set Key1="0123456789"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set WPAPSK="abcdefgh"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set NetworkType=Infra
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set AuthMode=WPAPSK
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set EncrypType=AES
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set Key1="0123456789"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set WPAPSK="abcdefgh"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set NetworkType=Infra
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set AuthMode=WPA2PSK
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set EncrypType=AES
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set WPAPSK="abcdefgh"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set NetworkType=Infra
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set AuthMode=WPA2PSK
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set EncrypType=TKIP
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set WPAPSK="abcdefgh"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="RT2880_AP"
#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set NetworkType=Adhoc
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set AuthMode=OPEN
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set EncrypType=NONE
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="fattt"
#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set NetworkType=Adhoc
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set AuthMode=WPANONE
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set EncrypType=TKIP
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="a"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set WPAPSK="abcdefgh"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 set SSID="a"

WPS 를 사용하기 위해서는 os/linux/config.mk 파일을 아래와 같이 수정해야 한다.

...
#ifdef WSC_INCLUDE
# Support WSC function
HAS_WSC=y
#endif // WSC_INCLUDE //
...

WiFi Dongle 의 PIN 번호를 알기 위해서는 다음과 같이 명령한다.

#./iwpriv ra0 stat
ra0       stat:
 
Tx success                      = 156
Tx success without retry        = 156
Tx success after retry          = 0
Tx fail to Rcv ACK after retry  = 0
RTS Success Rcv CTS             = 0
RTS Fail Rcv CTS                = 0
Rx success                      = 513
Rx with CRC                     = 384
Rx drop due to out of resource  = 0
Rx duplicate frame              = 0
False CCA (one second)          = 0
RSSI-A                          = 0
RSSI-B (if available)           = 0
RSSI-C (if available)           = 0
 
WPS Information(Driver Auto-Connect is Enabled):
RT2860 Linux STA PinCode        32934823        // PIN 번호
WPS not used.
 
WPS Profile Count               = 0

나중에 AP 에 위의 PIN 번호를 입력하면 된다. 다음과 같이 명령한다.

#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 wsc_conf_mode 1
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 wsc_mode 1
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 wsc_ssid "ASW"
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 wsc_start

실행 후에, AP 쪽에서 PIN 번호를 추가해주면 된다. 이후 'iwconfig' 명령어로 AP 에 접속이 되었는지 확인해본다.

#!/bin/sh
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 wsc_conf_mode 1
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 wsc_mode 2
/mnt/lg/lgapp/drivers/wireless_util/iwpriv ra0 wsc_start

실행 후에, AP 의 'WPS' 버튼을 누르면, 일정한 시간 후에 접속이 된다.

  • computer/lg/rt3572_사용하기.txt
  • Last modified: 4 years ago
  • by likewind