arm9+Linux fl2440 下的WiFi驱动rt3070的编译移植以及station模式

时间:2020-12-04 20:38:31

---------------------------------------------------------------------------------------------------------------------------------

                                               主机操作系统:centos 6.7

                                               交叉编译器版本:arm-linux-gcc-4.5.4

                                               开发板平台:fl2440

                                               linux内核版本:Linux-3.0

                                               开发 模板:ralink rt3070

                                               Author:  shaocongshuai <916962705@qq.com>

---------------------------------------------------------------------------------------------------------------------------------

实现RT3070无线网卡STA模式并使开发板接入Wifi上网

兼容IEEE 802.11b/g/n三种标准,传输速率150Mbps  

IEEE 802.11b,1999年,物理层补充(11Mbit/s工作在2.4GHz)。IEEE802.11g,2003年,物理层补充(54Mbit/s,工作在2.4GHz)。 IEEE 802.11n,2009年9月通过正式标准,WLAN的传输速率由802.11a802.11g提供的54Mbps、108Mbps,提高到350Mbps甚至到475Mbps。

4针式连接插孔,支持USB2.0(接口)信号输出;

支持64/128/152位WEP数据加密,支持多种无线加密方式

2.412 - 2.484GHz;

RT3070的工作模式分为 STA(station)模式、SoftAP(Access Point)模式两种。

STA模式:笔记本上无线网卡模式,用来连接到无线路由器上上网。通俗点说,就是客户端模式(笔记本)

AP模式:即作为无线路由器,提供其他用户接入 (路由器)

所以我们的驱动有两种,分别支持无来线网卡工作在STA模式AP模式。因为linux3.0以上的内核中已经含有了RT3070的通用mac80211驱动框架,所以我首先直接基于此并借助wpa_suppicant软件来实现Wifi的STA模式

 

一、进入内核配置界面,内核配置中需要做的修改如下:

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

        <*>   cfg80211 - wireless configuration API

        [*]   Wireless extensions sysfs files

       <*>   Generic IEEE 802.11 Networking Stack (mac80211)

        -*-   Common routines for IEEE802.11 drivers

        [*]     enable powersave by default

        [*]     cfg80211 wireless extensions compatibility


  Device Drivers  --->

       Generic Driver Options  --->

              [*]   Include in-kernel firmware blobs in kernel binary 

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

              <*>   IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)                                                            
              [*]     Support downloading firmware images with Host AP driver                                                              
              [*]       Support for non-volatile firmware download

              <M>   Ralink driver support  ---> 

                         <M>   Ralink rt27xx/rt28xx/rt30xx (USB) support

                         [*]   Ralink debug output

nl80211 / cfg80211 / mac80211不再使用的ioctl,他们使用 netlink (译者注:基于 socket 通信)

  • mac80211:是一个Linux内核子系统,是驱动开发者可用于为SoftMAC无线设备写驱动的框架。mac80211在内核空间实现STA模式,在用户空间实现AP模式(hostapd)。
  • cfg80211:用于对无线设备进行配置管理,与FullMAC,mac80211和nl80211一起工作。
  • nl80211:用于对无线设备进行配置管理,它是一个基本Netlink的用户态协议。
  • MLME:即MAC (Media Access Control) Layer Management Entity,它管理物理层MAC状态机。
  • SoftMAC:其MLME由软件实现,mac80211为SoftMAC实现提供了一个API。 即:SoftMAC设备允许对硬件执行更好地控制,允许用软件实现对802.11的帧管理,包括解析和产生802.11无线帧。目前大多数802.11设备为SoftMAC,而FullMAC设备较少。
  • FullMAC:其MLME由硬件管理,当写FullMAC无线驱动时,不需要使用mac80211。
  • wpa_supplicant:是用户空间一个应用程序,主要发起MLME命令,然后处理相关结果。
  • hostpad:是用户空间一个应用程序,主要实现station接入认证管理。

fg80211是Linux 802.11配置API。cfg80211用于代码wext(Wireless-Extensions),nl80211用于配置一个cfg80211设备,且用于kernel与userspace间的通信。wext现处理维护状态,没有新的功能被增加,只是修改bug。如果需要通过wext操作,则需要定义CONFIG_CFG80211_WEXT。

     cfg80211 and nl80211: 基于消息机制,使用netlink接口

    wext: 基于ioctl机制

mac80211

它是一个driver开发者可用于为SoftMAC无线设备写驱动的框架,mac80211为SoftMAC设备实现了cfg80211回调函数,且mac80211通过cfg80211实现了向网络子系统注册和配置。配置由cfg80211通过nl80211和wext实现。

    mac80211在体系结构中的位置如下图所示:

arm9+Linux fl2440 下的WiFi驱动rt3070的编译移植以及station模式

所以,像 iwhostapd 或 wpa_supplicant 之类的工具使用一些netlink的库(如  libnl 或 libnl-tiny)和netlink 接口通用头文件,当然这是 nl80211.h.

目前并没有多少相关的文档,但我建议你阅读 libnl documentation,和 iw source code (因为iw使用libnl)。


arm9+Linux fl2440 下的WiFi驱动rt3070的编译移植以及station模式

配置完之后

执行make


二:插入RT3070无线网卡并加载新内核启动 

1>内核信息打印部分

usb 1-1.3: new full speed USB device number 3 using s3c2410-ohci
phy0 -> rt2x00_set_chip: Info - Chipset detected - rt: 3070, rf: 0005, rev: 0201.

2>使用lsusb命令查看:

~ >: lsusb
Bus 001 Device 001: ID 1d6b:0001
Bus 001 Device 002: ID 05e3:0606
Bus 001 Device 003: ID 148f:3070

3>如果是热插拔的话会,在插入的那一刻,串口会打印如下信息:

~ >: usb 1-1.3: USB disconnect, device number 3
usb 1-1.2: new full speed USB device number 4 using s3c2410-ohci
phy1 -> rt2x00_set_chip: Info - Chipset detected - rt: 3070, rf: 0005, rev: 0201.

4>ifconfig查看网卡信息

~ >: ifconfig wlan0
wlan0     Link encap:Ethernet  HWaddr 00:24:25:50:A9:4D  
          BROADCAST MULTICAST  MTU:1500  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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

第一行:连接类型:Ethernet(以太网)HWaddr(硬件mac地址) 
第三行:MULTICAST(支持组播)MTU:1500(最大传输单元):1500字节 
第四、五行:接收、发送数据包情况统计 
第七行:接收、发送数据字节数统计信息。

5>使能RT3070无线网卡模块

~ >: ifconfig wlan0 up
phy1 -> rt2x00lib_request_firmware: Info - Loading firmware file 'rt2870.bin'.
phy1 -> rt2x00lib_request_firmware: Info - Firmware detected - version: 0.29.
phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 0 - CWmin: 3, CWmax: 4, Aifs: 2, TXop: 102.
phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 1 - CWmin: 4, CWmax: 5, Aifs: 2, TXop: 188.
phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 2 - CWmin: 5, CWmax: 10, Aifs: 3, TXop: 0.
phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 3 - CWmin: 5, CWmax: 10, Aifs: 7, TXop: 0.


三、无线网络配置工具Wireless tools和Wpa_supplicant以及Openssl移植 

目前可以使用wireless-toolswpa_supplicant工具来配置无线网络。但要注意对无线网络的配置是全局性的,而非针对具体的接口。wpa_supplicant是一个较好的选择,但缺点是它不支持所有的驱动。另外,wpa_supplicant目前只能连接到那些你已经配置好ESSID的无线网络。而wireless-tools支持几乎所有的无线网卡和驱动,但它不能连接到那些只支持WPAAP

1>Wireless tools移植

       Wireless Extension (WE)是一组通用的API,能在用户空间对通用Wireless LANs进行配置和统计。它的好处在于仅通过一组单一的工具就能对各种各样的Wireless LANs进行管理,不过它们是什么类型,只要其驱动支持Wireless Extension就行;另一个好处就是不用重启驱动或Linux就能改变这些参数。

       Wireless Tools (WT)就是用来操作Wireless Extensions的工具集,它们使用字符界面,虽然粗糙,但支持所有Wireless Extension。虽然还有很多其他管理Wireless Extensions的工具,但Wireless Tools是参考实现,它包括以下工具:

        iwconfig:设置基本无线参数

        iwlist:扫描、列出频率,比特率,密钥等

        iwspy:获取每个节点链接的质量

        iwpriv:操作Wireless Extensions 特定驱动

        ifrename: 基于各种静态标准命名接口

        大多数 Linux 发行版本都在其网络初始化脚本中集成Wireless Extension,以便启动时配置无线接口。他们还将Wireless Tools作为其标准封装包。

        无线配置也可以使用hotplug或uDev脚本来完成,需要发行版特定的支持,这样能支持任何可移动的无线接口(Pcmcia,CardBus,USB接口...)。

         Wireless Tools(从版本19)开始完全支持IEEE 802.11标准参数和设备,支持旧风格的设备和最专有协议,并准备处理HiperLan。较新版本增加了更多802.11支持。但不幸的是,并非所有的驱动程序支持所有这些功能。

  Wireless_tools

[shaocongshuai@localhost ~]$ tar -xzvf wireless_tools.29.tar.gz

[shaocongshuai@localhost ~]$ cd wireless_tools.29

修改Makefile

....

   7 ifndef PREFIX
  8   PREFIX = /home/shaocongshuai/wireless_tools.29/wirelesstoolsout
  9 endif
 10 
 11 ## Compiler to use (modify this for cross compile).
 12 CC = /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
 13 ## Other tools you need to modify for cross compile (static lib only).
 14 AR = /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-ar
 15 RANLIB =  /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-ranlib
 16 

.....

[shaocongshuai@localhost wireless_tools.29]$ make

[shaocongshuai@localhost wireless_tools.29]$ make install

在该目录下找到libiw.so.29,下载到开发板的/lib/目录下;再该目录下找到iwpriv、iwconfig、iwlist, iwevent, iwspy等命令,下载到开发板的/bin目录下。这时就应该可以使用这些命令通过网卡搜索到环境中的无线网络。


2>Openssl工具移植 

        OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。

下载地址  ftp://ftp.openssl.org/source/

[shaocongshuai@localhost ~]$ tar -xzvf openssl-0.9.8e.tar.gz

[shaocongshuai@localhost ~]$ cd openssl-0.9.8e

修改makefile

....
  28 INSTALL_PREFIX=
 29 INSTALLTOP=/home/shaocongshuai/openssl-0.9.8e/install
 30 
 31 # Do not edit this manually. Use Configure --openssldir=DIR do change this!
 32 OPENSSLDIR=/home/shaocongshuai/openssl-0.9.8e/install
 33 

...

  61 
 62 CC= /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
 63 CFLAG= -O
 64 DEPFLAG= -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_GMP -DOPENSSL_NO_MDC2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779
 65 PEX_LIBS=
 66 EX_LIBS=
 67 EXE_EXT=
 68 ARFLAGS=
 69 AR=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-ar $(ARFLAGS) r
 70 RANLIB=  /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-ranlib

 71 PERL= /usr/bin/perl

...

[shaocongshuai@localhost openssl-0.9.8e]$ make

[shaocongshuai@localhost openssl-0.9.8e]$ sudo make install

拷贝下面文件驱动到目标系统/usr/lib/
libssl.a
libcrypto.a
openssl 移植完成.


3>wpa_supplicant驱动移植

wpa_supplicant本是开源项目源码,被谷歌修改后加入Android移动平台,它主要是用来支持WEP,WPA/WPA2和WAPI无线协议和加密认证的,而实际上的工作内容是通过socket(不管是wpa_supplicant与上层还是wpa_supplicant与驱动都采用socket通讯)与驱动交互上报数据给用户,而用户可以通过socket发送命令给wpa_supplicant调动驱动来对WiFi芯片操作。 简单的说,wpa_supplicant就是WiFi驱动和用户的中转站外加对协议和加密认证的支持。

下载地址  http://w1.fi/releases/

[shaocongshuai@localhost ~]$ tar -xzvf wpa_supplicant-0.7.3.tar.gz

[shaocongshuai@localhost ~]$ cd wpa_supplicant-0.7.3/wpa_supplicant/
[shaocongshuai@localhost wpa_supplicant]$

[shaocongshuai@localhost wpa_supplicant]$ cp defconfig .config

[shaocongshuai@localhost wpa_supplicant]$ vim .config

...

 25 #### sveasoft (e.g., for Linksys WRT54G) ######################################
 26 #CC=mipsel-uclibc-gcc
 27 CC=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc -L /home/shaocongshuai/openssl-0.9.8e/install/lib/
 28 #CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
 29 #CFLAGS += -Os
 30 CFLAGS += -I /home/shaocongshuai/openssl-0.9.8e/install/include/
 31 #CPPFLAGS += -I../src/include -I../../src/router/openssl/include
 32 LIBS += -L /home/shaocongshuai/openssl-0.9.8e/install/lib/
 33 #LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl

...

[shaocongshuai@localhost wpa_supplicant]$ make

经过编译后的wpa_supplicant源程序可以看到三个主要的可执行工 具:wpa_supplicant、wpa_passphrase、wpa_cli。wpa_supplicant是核心程序,它和wpa_cli的关系就是服务和客户端的关系:后台运 行wpa_supplicant,使用wpa_cli来搜索、设置、和连接网络。


四、启动RT3070无线模块连接路由器 

一般的无线接入点可以用wpa_passphrase来自动生成

将wpa_supplicant下载到/bin,创建wpa_supplicant.conf的配置文件并进行编辑

~ >: vim wpa_supplicant.conf

network={
        ssid="breeze"
        proto=WPA
        key_mgmt=WPA-PSK  //认证密钥管理协议
        pairwise=CCMP TKIP //加密方式   TKIP和CCMP是两种数据加密算法,在WPA和WPA2中都可以使用。而AES是CCMP算法中的核心算法,且目前来看,是最可靠的加密算法。
        group=CCMP TKIP WEP104 WEP40 
        psk="y64z65w66l73"
        priority=2   //在其他的AP连接的优先级(0是默认的低优先级)
}

# proto: list of accepted protocols 支持的协议列表
# WPA = WPA/IEEE 802.11i/D3.0  # RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN) ---也能使用WPA2,它只是RSN的一个别名而已 # If not set, this defaults to: WPA RSN   ---如果不设置,默认就是WPA RSN,即全部支持
key_mgmt: list of accepted authenticated key management protocols  ---支持的协议列表  
WPA-PSK = WPA pre-shared key (this requires 'psk' field)     ---一般都是这个,这就包括了WPA、WPA2开始的那些方式
WPA-EAP = WPA using EAP authentication    ---这个就是WEP开头的,猜的,求验证
IEEE8021X = IEEE 802.1X using EAP authentication and (optionally) dynamically generated WEP keys 
NONE = WPA is not used; plaintext or static WEP could be used  ---这个是开放的,没密码,联通、电信之类的就这个  
 WPA-PSK-SHA256 = Like WPA-PSK but using stronger SHA256-based algorithms  
WPA-EAP-SHA256 = Like WPA-EAP but using stronger SHA256-based algorithms
If not set, this defaults to: WPA-PSK WPA-EAP ---如果未设置,默认支持WAP、WEP开头那些
pairwise: list of accepted pairwise (unicast) ciphers for WPA   ---WPA可用的加密方式列表  
 CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]  ---看到没,这个就是AES,换了马甲而已  
TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] ---TKIP 这个倒是没变 
NONE = Use only Group Keys (deprecated, should not be included if APs support pairwise keys)   ---这个估计很少用 
If not set, this defaults to: CCMP TKIP  ---不设置的话是CCMP TKIP,看似正确,其实有些路由器无法自动识别,只能二选一,很坑爹。  
 WPA是 Wi-Fi® Protected Access(Wi-Fi保护接入)的简称,是无线网络的数据加密规格. 它通过使用可扩展认证协议 (EAP) 提高WEP安全功能来确保网络使用的安全性,通过一种加密方法提高了数据传送的安全性.
      WPA使用802.1X认证服务器给每个用户分配不同的密钥. 但是它在安全性比较差的 "预先共享密钥 (PSK)" 模式中也有效. PSK用于家庭和小型办公室网络,每个用户都有同样的密码口令.  WPA-PSK 也叫做 WPA-Personal(WPA个人). WPA-PSK使用TKIP或AES加密方法把Brother无线设备和接入点联系起来.WPA2-PSK使用AES加密方法把Brother无线设备和接入点联系起来.
TKIP是 Temporal Key Integrity Protocol(临时密钥完整性协议)的简称,是一种加密方法.TKIP提供结合信息完整性检查和重新按键机制的信息包密钥.
AES是Advanced Encryption Standard(高级加密标准)的简称,是 Wi-Fi® 授权的高效加密标准.
WPA-PSK/WPA2-PSK和TKIP或AES使用预先共享密钥 (PSK),字符长度大于8并且小于6

其中的psk为无线网的密码
最后进行测试,测试之前要关闭有线网卡eth0,原因是如果不关闭的话在之后添加默认路由时会被设置为有线网卡的默认路由,这个应该有别的解决方法,不过我没有仔细去查。


~ >: ifconfig eth0 down

~ >: ifconfig wlan0 192.168.1.99 netmask 255.255.255.0

~ >: route add default gw 192.168.1.1

~ >: wpa_supplicant -B-Dwext -iwlan0 -c wpa_supplicant.conf 

-d:增加调试信息

-B:后台守护进程

-c:指定配置文件

-Dwextwext为驱动名称

-iwlan0 wlan0为网络接口名称

~ >: phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 2 - CWmin: 4, CWmax: 10, Aifs: 3, TXop: 0.
phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 3 - CWmin: 4, CWmax: 10, Aifs: 7, TXop: 0.
phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 1 - CWmin: 3, CWmax: 4, Aifs: 2, TXop: 94.
phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 0 - CWmin: 2, CWmax: 3, Aifs: 2, TXop: 47.

~ >: ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
Rcv Wcid(1) AddBAReq
Start Seq = 00000004
RTMP_TimerListAdd: add timer obj c49be074!
64 bytes from 192.168.1.1: seq=0 ttl=64 time=17.027 ms
64 bytes from 192.168.1.1: seq=1 ttl=64 time=2.325 ms
64 bytes from 192.168.1.1: seq=2 ttl=64 time=15.389 ms


如果你想上外网,那么就要给开发板添加DNS域名解析服务! 
在开发板的/etc/目录下创建一个resolv.conf的文件,因为在内核启动的时候内核会在resolv.conf文件中找dns
 
~>: vi resolv.conf 
nameserver 4.2.2.2 
nameserver 8.8.8.8

~ >: ping 4.2.2.2
PING 4.2.2.2 (4.2.2.2): 56 data bytes
64 bytes from 4.2.2.2: seq=0 ttl=51 time=346.248 ms
64 bytes from 4.2.2.2: seq=1 ttl=51 time=340.337 ms
64 bytes from 4.2.2.2: seq=2 ttl=51 time=333.143 ms


~ >: iwconfig
lo        no wireless extensions.
eth0      no wireless extensions.
ra0       Ralink STA  ESSID:"breeze"  Nickname:"RT2870STA"
          Mode:Managed  Frequency=2.462 GHz  Access Point: A8:57:4E:12:BD:60   
          Bit Rate=135 Mb/s   
          RTS thr:off   Fragment thr:off
          Encryption key:E6F9-8176-2FBC-4630-07F2-FF7C-6E7D-53B2   Security mode:restricted   Security mode:open
          Link Quality=100/100  Signal level:-43 dBm  Noise level:-57 dBm
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0


而我想要的是板子自己去动态随机获取IP联网,这样可以不用给wlan0指定IP。接下我们来完成这个功能。

首先我们在busybox里面make menuconfig配置好udhcp server(udhcpd)udhcp client(udhcpc)两个选项并编译,同时将新的内核放到开发板上。

然后从busyboxexamples/udhcp/copysimple.script文件到开发板/usr/share/udhcpc/下,并重命名为default.script.

注:(busybox里面默认的目录文件是/usr/share/udhcpc/default.script)


在上面启动无线网卡后我们便可以直接在开发板上面执行命令动态获取IP。

~ >: udhcpc -i wlan0
udhcpc (v1.20.2) started
Sending discover...
Sending select for 192.168.1.108...
Lease of 192.168.1.108 obtained, lease time 7200


遇到的问题:

~ >: ifconfig wlan0 up
phy0 -> rt2x00lib_request_firmware: Info - Loading firmware file 'rt2870.bin'.
phy0 -> rt2x00lib_request_firmware: Error - Failed to request Firmware.
ifconfig: SIOCSIFFLAGS: No such file or directory

通常情况下,load firmware的动作是通过用户空间的hotplug handler,也就是/proc/sys/kernel/hotplug里设定的执行档,来完成。root_qtopia默认会在/etc/init.d/rcS里将/proc/sys/kernel/hotplug设定为/sbin/mdev,即busybox的mdev模块。它在收到来自内核的请求加载rt73.bin这个firmware消息后,会从/lib/firmware目录下去找rt73.bin,如果能找到就加载。
解决方法:
文件系统的/etc/init.d/rcS加:
echo /sbin/mdev > /proc/sys/kernel/hotplug
这样一句。