1. 程式人生 > >嵌入式Linux開發板WIFI無線網絡卡驅動移植

嵌入式Linux開發板WIFI無線網絡卡驅動移植

本文所用開發板:tiny4412,當然也可以在jz2440上實現。

嵌入式中裝置想要聯網,無非就 有線和無線 兩種方式。

有線就插上網線,沒什麼好說的;無線的話一種是將WIFI模組整合焊接在板子上,另一種是WIFI模組以USB的方式接到板子上。

本次使用的就是USB介面的WIFI無線網絡卡,實現開發板使用WIFI無線網絡卡訪問網際網路和作為個人熱點。

1.準備工作

1.2 WIFI基礎知識

WIFI網絡卡有兩種工作模式,
一種是無線終端模式(STA),也就是手機日常使用的模式,通過該模式連線網路上網;
一種是無線熱點模式(AP),也就是手機的個人熱點模式,通過該模式提供熱點供其它裝置上網;

無線網路的安全性由兩部分組成:認證加密

認證: 使得只有允許的裝置才能連線到無線網路;
加密: 確保資料的保密性和完整性,即資料在傳輸過程中不會被篡改;

  • 常用的認證演算法有:開放認證、共享祕鑰認證、802.11x認證、PSK認證
    其中802.11x認證和PSK認證安全性較高,分別應用於企業和個人的環境;

  • 常用的加密演算法有:WEB加密、TKIP加密、CCMP加密演算法
    其中WEB加密和TKIP加密都是RC4的加密演算法,安全性較低;CCMP加密採用AES對稱加密演算法,安全性較高。

安全策略認證方式加密方式備註
Openopenopen開放WiFi,無任何加密
openWEP開放WiFi,僅資料加密
WEPWEPWEP共享金鑰認證,容易破解
WAP802.11XTKIP/WEP比較安全,用於企業
PSKTKIP/WEP比較安全,用於個人
WAP2802.11XCCMP/TKIP/WEP目前最安全,用於個人
PSKCCMP/TKIP/WEP目前最安全,用於個人

連入超市、商場等公共WIFI的時候,不需要輸入密碼,但要通過網頁輸入手機號,使用驗證碼驗證,也就是採用802.11X進行的驗證,通過伺服器完成的驗證。

使用手機開個人熱點的時候,可以選擇安全性OPEN、WEP、WAP、WAP2,也就對應不同的安全等級。

我手裡的MIX2S,MIUI10個人熱點裡面就僅OPEN和WAP2兩個選項,感覺這是個趨勢,要麼最簡單的OPEN,要麼就最安全的WAP2(WAP2是向下相容的),逐漸扔掉歷史的包袱。

1.2 選擇無線網絡卡

首先是選擇合適的無線網絡卡,選取的原則是根據WIFI無線網絡卡的VIDPID判斷核心是否支援該無線網絡卡。

  • 1.獲取無線網絡卡ID
    將無線網絡卡插入Windows電腦,開啟裝置管理器,選中無線網絡卡,右鍵“屬性”,切換到“詳細信”息選項卡,在“屬性”下拉欄中選擇”硬體ld”,即可得到無線網絡卡的ID:

我的無線網絡卡VID0x148FPID0x3070

  • 2.查詢核心是否支援
    可以從wireless.kernel.org得到支援的裝置列表
    可以從列表中搜到前面的VIDPID,因此說明核心是支援現在使用的無線網絡卡。此外,還可以得知對應的驅動應該為rt2800usbrt2870sta

1.3 移植WIFI驅動

  • 前面根據ID得到了對應的網絡卡驅動名字,但還不是很靠譜,建議直接在驅動中搜索ID,更靠譜:
grep "0x3070" drivers/net/wireless/ -nr

得到:
drivers/net/wireless/ralink/rt2x00/rt2800usb.c:1091: { USB_DEVICE(0x148f, 0x3070) },
知道了對應的驅動檔案是rt2800usb.c
 
- 再檢視對應路徑的Makfeile:

cat  drivers/net/wireless/ralink/rt2x00/Makefile 

得到:
obj-$(CONFIG_RT2800USB) += rt2800usb.o
知道了對應的巨集是CONFIG_RT2800USB
 
- 進入核心目錄,執行:

make menuconfig

搜尋CONFIG_RT2800USB,得知其依賴:
Depends on: NETDEVICES [=y] && WLAN [=y] && WLAN_VENDOR_RALINK [=y] && RT2X00 [=n] && USB [=y]
可以知道RT2X00 [=n]沒有開啟,再搜尋它,如此迴圈,直到
RT2800USB [=y]

這裡有個注意的就是,當開啟的上層的某個依賴,下層的某個選項可能會多出來許多選項,而這些選項原來是沒有的,不要固化思維。

最後重新編譯核心即可。

1.4 使用buildroot移植應用

想要使用無線網絡卡,需要用到四個軟體:
- iw:可用於OPEN、WEP這兩種”認證/加密”,以及掃描WIFI熱點等;
- wpa_supplicant:可用於前面4種”認證/加密”;
- hostapd:能夠使得無線網絡卡切換為AP模式;
- dhcp: STA模式使WIFI網絡卡動態獲取IP,AP模式分配IP;

也就是需要移植這四個軟體,目前的方法有:
1.逐個下載原始碼,交叉編譯,配置,可以還需要相關依賴庫,缺點是費時費力;

2.使用Yocto等工具,製作發行版的根檔案系統,例如Ubuntu16.04,裡面有apt-get,可以自動下載安裝,缺點是製作發行版根檔案系統比較麻煩,且體積較大;

3.使用buildroot製作根檔案系統,選擇需要的軟體,自動生成根檔案系統,相對簡單,體積也較小;

本次就以buildroot為例,製作包含應用程式的根檔案系統。

  • 首先從GitHub下載針對Tiny4412修改後的buidroot
git clone -b board_tiny4412 https://github.com/hceng/buildroot.git
  • 檢視支援的board
cd buildroot/
make list-defconfigs

得知tiny4412對應的配置檔案:
tiny4412_defconfig - Build for tiny4412

  • 配置提供的配置檔案
make tiny4412_defconfig
  • 新增自己所需軟體
    執行:
make menuconfig

對應勾選所需軟體:

Target packages  --->
    Networking applications  --->
        [*] dhcp (ISC)                                                
            [*]   dhcp server                                      
                [*]     Enable delayed ACK feature                     
            [*]   dhcp relay                                       
            [*]   dhcp client 
        ……
        [*] hostapd                                                     
            [*]   Enable ACS (NEW)                                      
            [*]   Enable EAP                                            
            [*]   Enable WPS 
        ……
        [*] iw
        ……
        [*] wpa_supplicant                                               
            [*]   Enable nl80211 support                                  
            [*]   Enable AP mode                                           
            [ ]   Enable EAP                                                  
            [ ]   Enable HS20                                                 
            [ ]   Enable syslog support                                       
            [ ]   Enable WPS                                                  
            [*]   Install wpa_cli binary                                      
            [*]   Install wpa_client shared library                           
            [*]   Install wpa_passphrase binary     
  • 修改主機名、歡迎語、root密碼等
System configuration  --->
    (tiny_4412) System hostname  
    (Welcome to hceng's board.) System banner  
    ……
    [*] Enable root login with password
    (123456) Root password 
  • 生成根檔案系統
    執行:
make

buildroot會自動下載相關原始碼包,整個過程時間比較久,最後生成buildroot/output/images/rootfs.tar,解壓到SD卡rootfs分割槽即可。

1.5 新增firmware

此時開發板啟動Linux後,使用ifconfig wlan0 up啟動無線網絡卡,提示:

ieee80211 phy0: rt2x00lib_request_firmware: Info - Loading firmware file 'rt2870.bin'
rt2800usb 2-2.2:1.0: Direct firmware load for rt2870.bin failed with error -2
ieee80211 phy0: rt2x00lib_request_firmware: Error - Failed to request Firmware
ifconfig: SIOCSIFFLAGS: No such file or directory

提示需要firmware檔案rt2870.bin

得到rt2870.bin後,拷貝到單板/lib/firmware/下即可。

1.6 啟動WIFI網絡卡

也就是先把有線網絡卡IP設定為其它網段,比如:

ifconfig eth0 192.168.2.220

然後啟動WIFI網絡卡,並設定IP(路由器IP為192.168.1.1):

ifconfig wlan0 up
ifconfig wlan0 192.168.1.220

此時效果如下:

2.無線終端模式——STA

完成前面的準備工作後,就可以通過軟體使用無線網絡卡了。

2.1 iw的使用

  • 列出WIFI網絡卡的效能:
iw list 
  • 掃描WIFI熱點
iw dev wlan0 scan 
iw dev wlan0 scan | grep SSID:
  • 連線到開放AP
iw wlan0 connect hceng
  • 檢視連線狀態
iw dev wlan0 link
  • 斷開WIFI連線
 iw wlan0 disconnect

還可以連線加密的WEP,這裡就不研究了。

注意:
1.如果連線的不是路由器(IP為192.168.1.1),而是Android手機熱點(IP一般為192.168.43.1),那麼要將WIFI網絡卡IP設定為43網段,如:192.168.43.10,才能ping通192.168.43.1
 
2.此時只能ping路由器和區域網裝置,如果要聯外網,還需要如下操作:
①修改/etc/resolv.conf,新增DNS:nameserver 192.168.1.1,如果是手機熱點為nameserver 192.168.43.1
②設定閘道器,輸入命令:route add default gw 192.168.1.1,如果是手機熱點為route add default gw 192.168.43.1

2.2 wpa_supplicant的使用

wpa_supplicant本是開源專案,被谷歌修改後加入android移動平臺,它主要是用來支援WEP,WPA/WPA2和WAPI無線協議和加密認證的。

wpa_supplicant是一個連線、配置WIFI的工具,它主要包含wpa_supplicant(命令列模式)與wpa_cli(互動模式)兩個程式。

通常情況下,可以通過wpa_cli來進行WIFI的配置與連線,如果有特殊的需要,可以編寫應用程式直接呼叫wpa_supplicant的介面直接開發。

記得以前想檢視Android手機連線過的WIFI熱點密碼時,就直接使用RE檔案管理器檢視/data/misc/wifi/wpa_supplicant.conf即可(需ROOT),裡面有所有連線過的WIFI名字和密碼。

從這裡可以看出,最後WIFI名字和密碼,都會被儲存到一個配置檔案裡,在Linux中,路徑就是/etc/wpa_supplicant.conf

  • 連線開放網路
    /etc/wpa_supplicant.conf加入:
network={
    ssid="hceng"
    key_mgmt=NONE
}

初始化wpa_supplicant,執行:

wpa_supplicant -B -d -i wlan0 -c /etc/wpa_supplicant.conf  

檢視連線狀態:

wpa_cli -iwlan0 status  

斷開連線:

wpa_cli -iwlan0 disconnect

killall wpa_supplicant

重新連線:

wpa_cli -iwlan0 reconnect
  • 連線加密網路(WAP2)
    /etc/wpa_supplicant.conf加入:
network={
    ssid="hceng_test"
    psk="12345678"
}

初始化wpa_supplicant,執行:

wpa_supplicant -B -d -i wlan0 -c /etc/wpa_supplicant.conf  

至於WEP和WAP方式,也就是配置檔案的不同,這裡就不去深究了,以後遇到了再說。

2.3 dhclient的使用

至此,已經可以連線WIFI了,但還有一些問題。

就如前面,需要手動設定裝置的IP,且要根據熱點的網段設定,還可能與同網段的裝置IP衝突。
為了解決這個問題,引入了DHCP,自動分配IP地址。

就像家裡的裝置連線到路由器一樣,除了輸入名字,密碼,其它都不用操作,而且還不會出現IP衝突的情況。

連線好WIFI後,輸入:

dhclient wlan0

實現自動獲取分配的IP,並設定。

2.4 自動指令碼

現在已經從功能上實現了WIFI無線網絡卡的使用,但使用過程步驟比較多,相對麻煩。
理想的效果無論何時插上WIFI無線網絡卡,都自動連線WIFI,且自動獲取IP地址。

這就要用到USB的熱拔插機制,很久以前寫過一篇U盤自動掛載的文章,用的就是這個機制。

  • 1.首先修改/etc/mdev.conf配置檔案
    加入WIFI無線網絡卡的熱拔插事件:
# hceng add for wifi
wlan0           root:root 660 * /sbin/auto_wifi.sh

其中*表示插拔都執行後面的指令碼。

  • 2.自動連線指令碼/sbin/auto_wifi.sh
    但檢測到USB網絡卡插拔後,就會執行該指令碼:
#!/bin/sh
if [ $ACTION = "add" ];
then
   echo --------usb wifi connect--------- > /dev/console
   wpa_supplicant -B -d -i wlan0 -c /etc/wpa_supplicant.conf
   wpa_cli -B -i wlan0 -a/sbin/auto_dhcp.sh
else
   echo --------usb wifi disconnect--------- > /dev/console
   killall wpa_supplicant
   killall wpa_cli
   killall dhclient
fi

如果是插入USB無線網絡卡,將執行wpa_supplicant -B -d -i wlan0 -c /etc/wpa_supplicant.conf連線wifi,再執行wpa_cli -B -i wlan0 -a/sbin/auto_dhcp.sh呼叫dhcp的指令碼;

如果是拔出USB無線網絡卡,將清除所有相關程序;

  • 3.自動dhcp指令碼/sbin/auto_dhcp.sh
#!/bin/sh
IFNAME=$1
CMD=$2
if [ "$CMD" = "CONNECTED" ]; then
   echo ========connect $IFNAME, dhclient for it======= > /dev/console
   dhclient $IFNAME
fi
if [ "$CMD" = "DISCONNECTED" ]; then
   echo ========disconnect $IFNAME, kill dhclient for it======= > /dev/console
   killall dhclient
fi

如果是連線,將呼叫dhclient分配IP,反之清除dhclient程序。

  • 4.為指令碼加上可執行許可權
chmod +x /sbin/auto_wifi.sh
chmod +x /sbin/auto_dhcp.sh

最後便可實現自動連線WIFI,且自動獲取IP地址。

3.無線熱點模式——AP

無線熱點模式共需要兩步操作,先使用hostapd將無線網絡卡切換成AP模式,再使用dhcpd分配IP。

3.1 hostapd的使用

先清除前面STA模式的所有操作,重新啟動單板。

  • 建立/etc/hostapd.conf配置檔案

1.OPEN模式:

ctrl_interface=/var/run/hostapd

ssid=hceng
channel=1
interface=wlan0
driver=nl80211

2.WAP/WAP2模式:

ctrl_interface=/var/run/hostapd

ssid=hceng
#hw_mode=g
channel=1
interface=wlan0
#bridge=br0
driver=nl80211
macaddr_acl=0
#accept_mac_file=/etc/hostapd.accept
#deny_mac_file=/etc/hostapd.deny

auth_algs=1
wpa=3
wpa_passphrase=12345678
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

註釋
ctrl_interface:為了後面hostapd_cli連結上hostapd
ssid:無線熱點名字;
hw_mode:指定802.11協議,其中a=IEEE 802.11ab=IEEE 802.11bg=IEEE 802.11g
channel:設定無線通道
interface:指定使用哪一個無線網絡卡;
bridge:指定所處網橋,對於一個同時接入公網、提供內部網和無線接入的路由器來說,設定網橋很有必要;
driver:指定無線驅動;
macaddr_acl:指定MAC地址過濾規則:
       0表示允許除禁止列表外的裝置;
       1表示只允許在允許列表的裝置;
       2表示使用外部RADIUS伺服器;
accept_mac_file:指定允許MAC列表檔案所在路徑;
deny_mac_file:指定禁止MAC列表檔案所在路徑;
auth_algs:指定採用哪種認證演算法,採用位域(bit fields)方式來制定;
      1表示使用WPA;
      2表示使用WEP;
      3表示使用WPA/WEP;
wpa:指定WPA型別,採用位域(bit fields)方式來制定;
   1表示使用WPA;
   2表示使用WPA2;
   3表示使用WPA2/WPA;
wpa_passphrase:WIFI的金鑰;
wpa_key_mgmt:PSK為個人AP,不使用伺服器認證;
wpa_pairwise:指定WPA的加密方式;
rsn_pairwise:指定WPA2的加密方式;

3.2 dhcpd的使用

如果此時啟動熱點,實測手機一直卡在獲取IP地址,無法連線到熱點,因此熱點還需自動分配IP地址。

subnet 192.168.2.0 netmask 255.255.255.0 {
  range 192.168.2.10 192.168.2.100;
  option domain-name-servers 192.168.2.1;
  option routers 192.168.2.1;
}

指定了子網IP起始地址、子網掩碼、動態分配的IP範圍、DNS伺服器、路由。

3.3 啟動熱點

  • 1.啟動無線網絡卡,並設定IP
ifconfig wlan0 up
ifconfig wlan0 192.168.2.1
  • 2.啟動AP和DHCP
    啟動命令:
hostapd -B /etc/hostapd.conf
dhcpd -cf /etc/dhcpcd.conf wlan0

對應的停止命令:

killall hostapd
killall dhcpd
  • 3.其它操作
    檢視熱點狀態:
hostapd_cli all_sta

檢視熱點配置:

hostapd_cli get_config

檢視已連線的裝置:

iw dev wlan0 station dump

3.4 自動指令碼

和前面的一樣,假如希望實現USB無線網絡卡的熱拔插,自動進入AP模式,只需如下操作:

  • 1.首先修改/etc/mdev.conf配置檔案
    加入WIFI無線網絡卡的熱拔插事件:
# hceng add for wifi
#wlan0           root:root 660 * /sbin/auto_wifi.sh
wlan0           root:root 660 * /sbin/auto_wifi_ap.sh
  • 2.自動AP指令碼/sbin/auto_wifi_ap.sh
    但檢測到USB網絡卡插拔後,就會執行該指令碼:
#!/bin/sh
if [ $ACTION = "add" ];
then                                
   echo --------usb wifi connect--------- > /dev/console
   hostapd -B /etc/hostapd.conf
   ifconfig wlan0 192.168.2.1
   dhcpd -cf /etc/dhcpcd.conf wlan0

else                     
   echo --------usb wifi disconnect--------- > /dev/console
   killall hostapd
   killall dhcpd
fi
  • 3.為指令碼新增可執行許可權
    執行:
chmod +x /sbin/auto_wifi_ap.sh

之後插上無線網絡卡,自動啟動熱點;拔掉無線網絡卡,自動關閉熱點。

參考教程:韋東山第3期視訊之WiFi網絡卡移植