歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android平台上無線網卡自動掃描並關聯AP的實現

最近為了驗證一個算法的能耗,研究了在開源的Android平台上如何實現無線網卡的自動開啟和基於wpa_supplicant的AP自動掃描和關聯,記錄且共享之。

目標:


自動打開無線網卡,掃描指定的信道列表,並在發現合適的AP時自動關聯。

1. Android平台的WiFi框架

Android平台使用的WiFi控制框架是基於大名鼎鼎的wpa_supplicant,它是一個安全中間件,為各種無線網卡提供統一的安全機制,如下圖所示:


圖1:Android平台WiFi框架


對應上述結構,基於Android 的G1手機中的WiFi控制分為三大組件:
1)客戶端程序,包括wpa_cli命令行或java圖形界面程序,通過unix本地socket與
wpa_supplicant daemon服務通信,發送命令並接收結果;
2)wpa_supplicant daemon服務,對應上述中間部分,功能是“上傳下達”。所有客戶端通過它控制硬件網卡,通過發送字符串命令控制是否掃描AP,提取掃描結果和是否關聯AP等操作,同時將驅動的執行狀態發送給用戶。該服務是設計支持多種無線網卡芯片,因此各個廠商共同提供了一個通用接口給wpa_supplicant調用,其中G1用的是TI的芯片;
3)網卡驅動,本文中可以不涉及。

2.    自動打開網卡並啟動wpa_supplicant
圖形界面可以正常啟動網卡並開始AP掃描,但通過命令行wpa_cli無法啟動,為此修改wpa_supplicant程序,輸出所有argv參數,然後通過圖形界面的設置來啟動AP掃描,設置->無線接口->啟動WiFi,輸出如下參數:
1257946571.827087: /system/bin/wpa_supplicant
1257946571.827453: -Dtiwlan0
1257946571.827545: -itiwlan0
1257946571.827636: -c/data/misc/wifi/wpa_supplicant.conf
手工輸入 wpa_supplicant -Dtiwlan0 -itiwlan0 -c/data/misc/wifi/wpa_supplicant.conf 還是啟動失敗。通過跟蹤圖形界面的java代碼,定位android/packages/apps/Settings/src/com/android/settings/wifi下的java文件,確定是WifiEnabler.java,調用路徑為:WifiEnabler->WifiManager.setWifiEnabled 接口函數,通過AIDL->WifiServic.setWifiEnabled函數,它向自身發送一條 MESSAGE_ENABLE_WIFI 消息, 處理代碼handleMessage中調用setWifiEnabledBlocking,該函數代碼如下:

if (enable) {
if (!WifiNative.loadDriver()) {}
if (!WifiNative.startSupplicant()) {}
..... } else {
if (!WifiNative.stopSupplicant()) {}     
if (!WifiNative.unloadDriver()) { }

}
}
WifiNative.java使用JNI機制,對應的c文件是android/hardware/libhardware_legacy/wifi/wifi.c, 其中包括以下核心函數:
int wifi_load_driver();
int wifi_unload_driver();
int wifi_start_supplicant();
int wifi_stop_supplicant();

It’s great! 將該文件靜態鏈接到我們的代碼中就可以自動加載網卡和啟動wpa_supplicant。

3.    自動掃描指定的信道,並關聯給定的AP

現有的wpa_cli是一個交互式命令環境,在連接到wpa_supplicant服務後,通過請求-響應的方式工作。因此我們需要重寫一個客戶端wpa_myclient,並通過前述wifi.c代碼自動打開網卡並啟動wpa_supplicant,涉及代碼文件包括:
android/external/wpa_supplicant/
android/system/wlan/ti/wpa_supplicant_lib/:是由TI公司提供給wpa_supplicant的統一接口

1)    分析wpa_cli的工作原理,確定通過手工命令如何關聯AP
術語networks是指由當前網卡已記憶的WLAN網絡,與windows無線接口設置中的“首選網絡”概念類似,該網絡也可以通過wpa_supplicant.conf手工配置
術語scan_results是指當前網卡掃描發現的AP。
網卡通過需要使用下列命令序列來關聯一個網絡:
scan
scan_results %獲得掃描結果,包括ssid和信號強度等信息
add_network %必須先創建一個網絡,得到一個新的網絡號id
set_network id ssid “***” %將網絡與想關聯AP的SSID對應
set_network id key_mgmt NONE %設置安全信息,這裡是針對Open System
set_network id pairwise NONE
select_network id %激活該網絡,此時開始關聯過程

2)    分析wpa_cli與supplicant的通信協議,添加一個新的命令MYSCAN能按指定信道列表掃描,並修改核心數據結構struct wpa_supplicant加入一個成員保存待掃描的信道列表,主要修改文件包括:ctrl_iface.c和wpa_supplicant_i.h
3)    由wpa_supplicant.c的wpa_supplicant_scan()->driver_ti.c的wpa_driver_tista_scan-> ti_init_scan_params()初始化掃描參數,將pScanParams->channelEntry設置為指定的信道列表;
4)    掃描結束後,驅動程序通過driver_ti.c的wpa_driver_tista_receive_driver_event()通知調用程序,該事件通過逐級傳遞到events.c 的wpa_supplicant_event()事件分發接口, 並通過wpa_supplicant_event_scan_results()通知wpa_cli客戶端,指示用戶可以使用scan_results命令獲取掃描結果;此外在該處理函數中如果發現掃描結果包括用戶的首選網絡networks,則會自動啟動關聯過程(windows也是這種方式)。
5)    修改events.c 的wpa_supplicant_event_scan_results()來模擬用戶首選網絡,首先利用    wpa_config_remove_network方法刪除wpa_s->conf->ssid 中的所有首選網絡,並根據一個規則從wpa_s->scan_results[]中選擇一個最合適的,然後通過wpa_config_add_network和wpa_config_set按照上述手工命令格式設置該network,然後它將自動按照正常流程關聯。

Hints and Tips:
1)    在android根目錄執行命令,. build/envsetup.sh,然後就可以使用mm TARGET_PRODUCT=htc_dream命令加速編譯
2)    實現命令set_network id ssid “***”,不能少了SSID的雙引號
3)    為了實現將輸出調試信息到文件,需要在.config中打開編譯開關CONFIG_DEBUG_FILE,同時在main.c中初始化params.wpa_debug_file_path為一個文件(我的是/sdcard/wpadbg),最後自定義一個wpa_printf的消息優先級,並打開wpa_debug_print_timestamp,輸出時戳。
Copyright © Linux教程網 All Rights Reserved