嵌入式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對稱加密演算法,安全性較高。
安全策略 | 認證方式 | 加密方式 | 備註 |
---|---|---|---|
Open | open | open | 開放WiFi,無任何加密 |
open | WEP | 開放WiFi,僅資料加密 | |
WEP | WEP | WEP | 共享金鑰認證,容易破解 |
WAP | 802.11X | TKIP/WEP | 比較安全,用於企業 |
PSK | TKIP/WEP | 比較安全,用於個人 | |
WAP2 | 802.11X | CCMP/TKIP/WEP | 目前最安全,用於個人 |
PSK | CCMP/TKIP/WEP | 目前最安全,用於個人 |
連入超市、商場等公共WIFI的時候,不需要輸入密碼,但要通過網頁輸入手機號,使用驗證碼驗證,也就是採用802.11X進行的驗證,通過伺服器完成的驗證。
使用手機開個人熱點的時候,可以選擇安全性OPEN、WEP、WAP、WAP2,也就對應不同的安全等級。
我手裡的MIX2S,MIUI10個人熱點裡面就僅OPEN和WAP2兩個選項,感覺這是個趨勢,要麼最簡單的OPEN,要麼就最安全的WAP2(WAP2是向下相容的),逐漸扔掉歷史的包袱。
1.2 選擇無線網絡卡
首先是選擇合適的無線網絡卡,選取的原則是根據WIFI無線網絡卡的VID
和PID
判斷核心是否支援該無線網絡卡。
- 1.獲取無線網絡卡ID
將無線網絡卡插入Windows電腦,開啟裝置管理器,選中無線網絡卡,右鍵“屬性”,切換到“詳細信”息選項卡,在“屬性”下拉欄中選擇”硬體ld”,即可得到無線網絡卡的ID:
我的無線網絡卡VID
是0x148F
,PID
是0x3070
;
- 2.查詢核心是否支援
可以從wireless.kernel.org得到支援的裝置列表。
可以從列表中搜到前面的VID
和PID
,因此說明核心是支援現在使用的無線網絡卡。此外,還可以得知對應的驅動應該為rt2800usb
、rt2870sta
。
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.11a
,b=IEEE 802.11b
,g=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網絡卡移植