Softap命令和Wi-Fi有紧密关系。本节先简单介绍Soft AP相关的背景知识,后续章节将对Wi-Fi开展深入讨论。
(1)背景知识介绍
Soft AP代表通过软件实现Access Point的功能。那么AP是什么?AP和Soft AP有什么不同?
在Wi-Fi无线技术规范中,AP和Station是其中的两个基本概念。
从功能角度来看,AP作为基站设备,起着连接其他无线设备到有线网的作用,相当于有线网络中的HUB与交换机。在日常工作和家庭中经常使用的无线路由器就是一个AP。一般情况下,它一端接着有线网络,另一端连接其他无线设备。
Station代表配备无线网络接口的设备,如手机、笔记本等。
虽然AP和Station是两个不同的设备,但实际上在Station中用软件也能实现AP拥有的功能,如桥接、路由等。在基本功能上,Soft AP与AP并没有太大的差别,只是Soft AP设备的接入能力和覆盖范围不如AP。
以前面提到的高铁列车上的应用场景为例,除了用USB绑定外,还可以打开笔记本和手机的Wi-Fi,并启动手机的Soft AP功能。这样,手机一方面用3G接入互联网,另一方面又利用Soft AP向笔记本提供Wi-Fi接入功能。
在Android系统中使用Soft AP功能还得借助另一个开源软件“hostapd”,这是一个运行在用户空间的用于AP和认证服务器的守护进程。它实现了IEEE 802.11相关的接入管理、IEEE 802.1X/WPA/WPA2/EAP 认证、RADIUS客户端、EAP服务器和RADIUS认证服务器。
(2)SoftapCmd命令使用
和TetherCmd类似,开启Android中手机的Soft AP功能将涉及大量Framework层中的操作,本节仅关注和Netd相关的三个步骤。
1)首先为Wi-Fi加载不同的固件(Firmware),这是通过SoftapController的fwReloadSoftap函数完成的,代码如下所示。
[-->SoftapController.cpp::fwReloadSoftap]
int SoftapController::fwReloadSoftap(int argc, char *argv[])
{
int ret, i = 0;
char *iface;
char *fwpath;
......// 参数检测
iface = argv[2];
if (strcmp(argv[3], "AP") == 0) {
fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
} else if (strcmp(argv[3], "P2P") == 0) {
fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
} else {
fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
}
// 通过往/sys/module/wlan/parameters/fwpath文件中写入固件名
// 触发驱动去加载对应的固件
ret = wifi_change_fw_path((const char *)fwpath);
......
return ret;
}
上面这段代码表示在Android中,如果要让Wi-Fi无线设备扮演不同的角色,得为它们加载不同的固件(Firmware),具体说明如下。
WIFI_GET_FW_PATH_AP:代表Soft AP功能的固件,其对应的文件位置由WIFI_DRIVER_FW_PATH_AP宏表达。三星Tuna平台中,该文件位置为/vendor/firmware/fw_bcmdhd_apsta.bin。
WIFI_GET_FW_PATH_P2P:代表P2P功能的固件,其对应的文件位置由WIFI_DRIVER_FW_PATH_P2P宏表达。三星Tuna平台中,该文件位置为/vendor/firmware/ fw_bcmdp2p.bin。
WIFI_GET_FW_PATH_STA:代表Station功能的固件,其对应的文件位置由WIFI_DRIVER_FW_PATH_STA宏表达。三星Tuna平台中,该文件位置为/vendor/firmware/fw_bcmdhd.bin。
提示 三星Tuna平台对应的配置文件在Android 4.2源码根目录/device/samsung/tuna目录中。从上面的固件文件名来看,它用的Wi-Fi无线芯片是博通(Broadcom)公司生产的。通过加载不同固件的方式来启用无线芯片硬件的不同功能可能和Wi-Fi驱动及芯片的设计有关。
另外,根据审稿专家的反馈,在Android 4.2中,STA和P2P可同时运行(即所谓的共存模式),这样STA和P2P实际对应的固件相同,但可能文件名不同。而SoftAP的固件与STA/P2P就不一样了。
2)加载完指定的Wi-Fi固件后,下一步将对Soft AP功能进行一些配置,配置信息最终将写到一个配置文件。这部分功能由SoftapController的setSoftap函数完成,代码如下所示。
[-->SoftapController.cpp::setSoftap]
int SoftapController::setSoftap(int argc, char *argv[]) {
char psk_str[2*SHA256_DIGEST_LENGTH+1];
int ret = 0, i = 0, fd;
char *ssid, *iface;
......// 参数检查
iface = argv[2];
char *wbuf = NULL;
char *fbuf = NULL;
if (argc > 3) {
ssid = argv[3];
} else {
ssid = (char *)"AndroidAP"; // SSID即接入点的名称
}
asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="
"/data/misc/wifi/hostapd\nssid=%s\nchannel=6\nieee80211n=1\n",
iface, ssid);
if (argc > 4) { // 判断AP的加密类型
if (!strcmp(argv[4], "wpa-psk")) {
generatePsk(ssid, argv[5], psk_str);
asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n",
wbuf, psk_str);
} else if (!strcmp(argv[4], "wpa2-psk")) {
generatePsk(ssid, argv[5], psk_str);
asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n",
wbuf, psk_str);
} else if (!strcmp(argv[4], "open")) {
asprintf(&fbuf, "%s", wbuf);
}
} ......
// HOSTAPD_CONF_FILE指向/data/misc/wifi/hostapd.conf文件
fd = open(HOSTAPD_CONF_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0660);
......
if (write(fd, fbuf, strlen(fbuf)) < 0) {
ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
ret = -1;
}
......// 修改该文件的读写权限等
return ret;
}
上面代码中涉及Wi-Fi技术的很多概念,将在后续章节统一介绍。从功能上来说,setSoftap函数无非就是把一些配置信息写到一个hostapd.conf文件中。可以通过一个例子文件来了解此文件的内容。
Android4.2/hardware/ti/wlan/mac80211/config目录中有一个hostapd.conf文件,其内容如下所示。
[-->hostapd.conf]
driver=nl80211 #指定Wi-Fi驱动的名称
......#略去部分内容
ssid=AndroidAP #设置接入点名称为AndroidAP
country_code=US
wep_rekey_period=0
eap_server=0
own_ip_addr=127.0.0.1
wpa_group_rekey=0
wpa_gmk_rekey=0 #加密方式等设置
wpa_ptk_rekey=0
interface=wlan1 #网络设备接口
......#略去部分内容
由上边示例的hostapd.conf可知,当使用该配置文件后,其他Station搜索到由这台手机设置的Soft AP的名称将会是“AndroidAP”。
3)最后,SoftapController的startap函数被调用,它将启动hostapd进程。重点关注hostapd启动的参数信息,如下所示。
hostapd \
-e /data/misc/wifi/entropy.bin \和Wi-Fi协议中的信息加密有关
/data/misc/wifi/hostapd.conf \hostapd的配置文件