Only To developers.
wpa_supplicant 0.8.X, wpa_supplicant_drvier nl80211, wifi chip bcm4330.
Patch
修改Settings/wifi中的代码以显示[IBSS][WEP] ssid或没有名字的ssid.
当UI显示SSID列表时,会获取从wpa_supplicant最近扫描到的APs;wpa_supplicant的输出扫描结果并没有过滤掉IBSS或隐藏的APs。
In constructAccessPoints()@WifiSettings.java,
final List<ScanResult> results = mWifiManager.getScanResults(); //同步操作
if (results != null) {
for (ScanResult result : results) {
// Ignore hidden and ad-hoc networks.
if (result.SSID == null || result.SSID.length() == 0 /* || result.capabilities.contains("[IBSS]")*/) {
continue;
}
修改wpa_supplicant,设置IBSS spot工作模式配置和连接时避免跳过
当第一次点击连接IBSS/ADHOC AP时,会弹出输入密码对话框,wpa_supplicant会将AP configuration信息保存到wpa_supplicant.conf中;此时保存该IBSS AP的工作模式为mode=1,保存到wpa_supplicant.conf中。
Inwpa_supplicant_ctrl_iface_set_network(…)@ctrl_iface.c
static int wpa_supplicant_ctrl_iface_set_network(
struct wpa_supplicant *wpa_s, char *cmd)
{
int id;
struct wpa_ssid *ssid;
char *name, *value;
struct wpa_bss *bss;
/* cmd: "<network id> <variable name> <value>" */
name = os_strchr(cmd, ' ');
if (name == NULL)
return -1;
*name++ = '\0';
value = os_strchr(name, ' ');
if (value == NULL)
return -1;
*value++ = '\0';
id = atoi(cmd);
wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
id, name);
wpa_hexdump_ascii_key(MSG_INFO, "CTRL_IFACE: value",
(u8 *) value, os_strlen(value));
ssid = wpa_config_get_network(wpa_s->conf, id);
if (ssid == NULL) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
"id=%d", id);
return -1;
}
if (wpa_config_set(ssid, name, value, 0) < 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
"variable '%s'", name);
return -1;
}
if (os_strcmp(name, "ssid") == 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: check if hook %s ssid->mode to 1(IBSS) ", value);
bss = NULL;
dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
if(bss->ssid) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: bss ssid foreach '%s'", bss->ssid);
if(os_strncmp(bss->ssid, value+1, os_strlen(bss->ssid))==0 && (bss->caps & IEEE80211_CAP_IBSS))
{
wpa_printf(MSG_DEBUG, "CTRL_IFACE: find matched ssid for '%d', try to set IBSS mode", id);
if (wpa_config_set(ssid, "mode", "1", 0) < 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: failed to set IBSS mode on '%d'", id);
return -1;
}
wpa_printf(MSG_DEBUG, "CTRL_IFACE: hook to set IBSS mode on '%d' successfully", id);
}
}
/* loop all bssid for the ssid */
}
}
当长按AP点击连接时,wpa_supplicant会将AP和扫描结果与配置库中的AP比对,如果为IBSS,则被跳过。
在wpa_scan_res_match(…)@events.c中,修改
if (bss->caps & IEEE80211_CAP_IBSS) {
wpa_dbg(wpa_s, MSG_DEBUG, "skip - IBSS (adhoc) "
"network");
continue;
}
为
if ((bss->caps & IEEE80211_CAP_IBSS)&& (ssid->mode!=IEEE80211_MODE_IBSS)) {
wpa_dbg(wpa_s, MSG_DEBUG, "skip - IBSS (adhoc) "
"network");
continue;
}
linux内核nl80211驱动和bcm4330驱动
wpa_driver_nl80211_ibss发送NL80211_CMD_SET_INTERFACE和 NL80211_CMD_JOIN_IBSS经linux nl80211 driver交给bcm4330 common driver处理。
NL80211_CMD_SET_INTERFACE投递给wl_cfg80211_change_virtual_iface时,需要切换bcm4330固件工作模式到IBSS模式;增加网卡工作模式INFRA/ADHOC设置代码如下,
In wl_cfg80211_change_virtual_iface(…) @ wl_cfg80211.c
if (ap) {
wl_set_mode_by_netdev(wl, ndev, mode);
if (wl->p2p_supported && wl->p2p->vif_created) {
……………………………….
}
} else {
wl_set_mode_by_netdev(wl, ndev, mode);
printk("try to set infra in wl_cfg80211_change_virtual_iface: value=%d, mode=%s", infra, (infra==1)?"INFRA":"ADHOC");
err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
if (unlikely(err)) {
WL_ERR(("WLC_SET_INFRA mode failed with error (%d)\n", err));
return err;
}
}
NL80211_CMD_JOIN_IBSS投递给wl_cfg80211_join_ibss时,修改代码如下,
In wl_cfg80211_join_ibss @ wl_cfg80211.c
static s32
wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params)
{
struct wl_priv *wl = wiphy_priv(wiphy);
struct cfg80211_bss *bss;
struct ieee80211_channel *chan;
struct wl_join_params join_params;
struct cfg80211_ssid ssid;
s32 scan_retry = 0;
size_t join_params_size = 0;
s32 err = 0;
bool rollback_lock = false;
s32 wsec = 0;
s32 bcnprd;
s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
//WL_TRACE(("In\n"));
printk("In wl_cfg80211_join_ibss\n");
CHECK_SYS_UP(wl);
if (params->bssid) {
//WL_ERR(("Invalid bssid\n"));
printk("wl_cfg80211_join_ibss: with bssid, overwrite EOPNOTSUPP originally\n");
//return -EOPNOTSUPP;
}
bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
/* scarely bss==null */
if (!bss) {
memcpy(ssid.ssid, params->ssid, params->ssid_len);
ssid.ssid_len = params->ssid_len;
do {
if (unlikely
(__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
-EBUSY)) {
wl_delay(150);
} else {
break;
}
} while (++scan_retry < WL_SCAN_RETRY_MAX);
/* to allow scan_inform to propagate to cfg80211 plane */
if (rtnl_is_locked()) {
rtnl_unlock();
rollback_lock = true;
}
/* wait 4 secons till scan done.... */
schedule_timeout_interruptible(4 * HZ);
if (rollback_lock)
rtnl_lock();
bss = cfg80211_get_ibss(wiphy, NULL,
params->ssid, params->ssid_len);
}
if (bss) {
wl->ibss_starter = false;
//WL_DBG(("Found IBSS\n"));
printk("wl_cfg80211_join_ibss: Found IBSS\n");
} else {
wl->ibss_starter = true;
printk("wl_cfg80211_join_ibss: Still not Found IBSS\n");
}
/* Configure Privacy for starter */
if (params->privacy)
wsec |= WEP_ENABLED;
/* set auth to open */
err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
if (err < 0) {
WL_ERR(("auth error %d\n", err));
return BCME_ERROR;
}
/* set wsec */
err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
if (err < 0) {
WL_ERR(("wsec error %d\n", err));
return BCME_ERROR;
}
/* set upper-layer auth */
err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", 0, bssidx);
if (err < 0) {
WL_ERR(("wpa_auth error %d\n", err));
return BCME_ERROR;
}
/* Configure Beacon Interval for starter */
if (params->beacon_interval)
bcnprd = htod32(params->beacon_interval);
else
bcnprd = htod32(100);
err = wldev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd), true);
if (unlikely(err)) {
WL_ERR(("WLC_SET_BCNPRD failed (%d)\n", err));
goto done;
}
chan = params->channel;
if (chan) {
u32 target_channel;
wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
if (params->channel_fixed) {
/* adding chanspec */
wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
}
/* set channel for starter */
target_channel = htod32(wl->channel);
err = wldev_ioctl(dev, WLC_SET_CHANNEL, &target_channel, sizeof(target_channel), true);
if (unlikely(err)) {
WL_ERR(("WLC_SET_CHANNEL failed (%d)\n", err));
goto done;
}
} else {
printk("wl_cfg80211_join_ibss: with zero wl->channel\n");
wl->channel = 0;
}
/*
* Join with specific BSSID and cached SSID
* If SSID is zero join based on BSSID only
*/
memset(&join_params, 0, sizeof(join_params));
memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, params->ssid_len);
join_params.ssid.SSID_len = htod32(params->ssid_len);
wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
if (params->bssid) {
memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
join_params_size = sizeof(join_params.ssid) + WL_ASSOC_PARAMS_FIXED_SIZE;
} else {
//memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN);
join_params_size = sizeof(join_params.ssid);
}
wl_update_prof(wl, dev, NULL, &join_params.params.bssid, WL_PROF_BSSID);
printk("wl_cfg80211_join_ibss: before wldev_ioctl\n");
//err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, sizeof(join_params), false);
err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
if (unlikely(err)) {
WL_ERR(("Error (%d)\n", err));
printk("wl_cfg80211_join_ibss:: Error (%d)\n", err);
return err;
}
wl_set_drv_status(wl, CONNECTING, dev);
done:
WL_TRACE(("Exit\n"));
return err;
}
In __wl_cfg80211_scan(…) @ wl_cfg80211.c
if (request) {/* scan bss */
改为
if (request && !wl_is_ibssmode(wl, ndev)) {/* scan bss */
In wl_cfg80211_get_station(…)@ wl_cfg80211.c
} else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) {
改为
} else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS || wl_is_ibssmode(wl, dev)) {
增加函数wl_inform_ibss@ wl_cfg80211.c
static s32
wl_inform_ibss(struct wl_priv *wl, struct net_device *dev, const u8 *bssid)
{
struct wiphy *wiphy = wl_to_wiphy(wl);
struct ieee80211_channel *notify_channel;
struct wl_bss_info *bi = NULL;
struct ieee80211_supported_band *band;
u8 *buf = NULL;
s32 err = 0;
u16 channel;
u32 freq;
u64 notify_timestamp;
u16 notify_capability;
u16 notify_interval;
u8 *notify_ie;
size_t notify_ielen;
s32 notify_signal;
printk("Enter wl_inform_ibss\n");
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
if (buf == NULL) {
WL_ERR(("kzalloc() failed\n"));
err = -ENOMEM;
goto CleanUp;
}
*(u32 *)buf = htod32(WL_BSS_INFO_MAX);
err = wldev_ioctl(dev, WLC_GET_BSS_INFO, buf, WL_BSS_INFO_MAX, false);
if (unlikely(err)) {
WL_ERR(("WLC_GET_BSS_INFO failed: %d\n", err));
goto CleanUp;
}
bi = (wl_bss_info_t *)(buf + 4);
channel = bi->ctl_ch ? bi->ctl_ch :
CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
if (channel <= CH_MAX_2G_CHANNEL)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
freq = ieee80211_channel_to_frequency(channel, band->band);
notify_channel = ieee80211_get_channel(wiphy, freq);
notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
notify_capability = le16_to_cpu(bi->capability);
notify_interval = le16_to_cpu(bi->beacon_period);
notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
notify_ielen = le16_to_cpu(bi->ie_length);
notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
WL_DBG(("channel: %d(%d)\n", channel, freq));
WL_DBG(("capability: %X\n", notify_capability));
WL_DBG(("beacon interval: %d\n", notify_interval));
WL_DBG(("signal: %d\n", notify_signal));
WL_DBG(("notify_timestamp: %#018llx\n", notify_timestamp));
cfg80211_inform_bss(wiphy, notify_channel, bssid,
notify_timestamp, notify_capability, notify_interval,
notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
CleanUp:
kfree(buf);
printk("Exit wl_inform_ibss\n");
return err;
}
当得到WLC_E_LINK成功和WLC_E_SET_SSID成功时,通知用户态。
In wl_notify_connect_status(…)@ wl_cfg80211.c
} else {
WL_DBG(("wl_notify_connect_status : event %d status : %d \n",
ntoh32(e->event_type), ntoh32(e->status)));
if((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DISASSOC_IND)) {
reason = ntoh32(e->reason);
WL_ERR(("Received %s event with reason code: %d\n", (event == WLC_E_DEAUTH_IND)? "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason));
}
if (wl_is_linkup(wl, e, ndev)) {
wl_link_up(wl);
act = true;
wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
if (wl_is_ibssmode(wl, ndev)) {
printk("linkup in ibss mode, before to call cfg80211_ibss_joined\n");
wl_inform_ibss(wl, ndev, (s8 *)&e->addr);
cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
GFP_KERNEL);
wl_clr_drv_status(wl, CONNECTING, ndev);
wl_set_drv_status(wl, CONNECTED, ndev);
WL_DBG(("joined in IBSS network\n"));
} else {
…………………………….
}
if (wl_get_drv_status(wl, CONNECTING, ndev)) {
if (wl_is_ibssmode(wl, ndev))
wl_clr_drv_status(wl, CONNECTING, ndev);
else
wl_bss_connect_done(wl, ndev, e, data, false);
}
} else {
printk("%s nothing\n", __FUNCTION__);
}
}
Patch END.
Control flow
Settings/Wifi UI part structure
WifiSettings是主对话框
167
168@Override
169public void onActivityCreated(Bundle savedInstanceState) {
170// We don't call super.onActivityCreated() here, since it assumes we already set up
171// Preference (probably in onCreate()), while WifiSettings exceptionally set it up in
172// this method.
173
174mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
175mWifiManager.asyncConnect(getActivity(), new WifiServiceHandler());
176if (savedInstanceState != null
177&& savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) {
178mDlgEdit = savedInstanceState.getBoolean(SAVE_DIALOG_EDIT_MODE);
179mAccessPointSavedState = savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE);
180}
1101public void asyncConnect(Context srcContext, Handler srcHandler) {
1102mAsyncChannel.connect(srcContext, srcHandler, getMessenger());
1103}
establish a half connect between WifiManager and WifiService.
1117public void connectNetwork(WifiConfiguration config) {
1118if (config == null) {
1119return;
1120}
1121mAsyncChannel.sendMessage(CMD_CONNECT_NETWORK, config);
1122}
ContextMenu是长按的三菜单Menu
@Override
public boolean onContextItemSelected(MenuItem item) {
if (mSelectedAccessPoint == null) {
return super.onContextItemSelected(item);
}
switch (item.getItemId()) {
case MENU_ID_CONNECT: {
if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
if (!requireKeyStore(mSelectedAccessPoint.getConfig())) {
mWifiManager.connectNetwork(mSelectedAccessPoint.networkId);
}
} else if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE) {
/** Bypass dialog for unsecured networks */
mSelectedAccessPoint.generateOpenNetworkConfig();
mWifiManager.connectNetwork(mSelectedAccessPoint.getConfig());
} else {
showConfigUi(mSelectedAccessPoint, true);
}
return true;
}
case MENU_ID_FORGET: {
mWifiManager.forgetNetwork(mSelectedAccessPoint.networkId);
return true;
}
case MENU_ID_MODIFY: {
showConfigUi(mSelectedAccessPoint, true);
return true;
}
}
return super.onContextItemSelected(item);
}
onPreferenceTreeClick是点击使能选项,使能Wifi。
WifiConfigController是MVC中的Controller
WifiDialog是单击的config对话框
In IWifiManager.aidl
32interface IWifiManager {};
In WifiService.java
public class WifiService extends IWifiManager.Stub {};
In WifiManager.java, NOT the intermediate file of IWifiManager.aidl
485public WifiManager(IWifiManager service, Handler handler) {
486mService = service;
487mHandler = handler;
488}
In ContextImpl.java
449registerService(WIFI_SERVICE, new ServiceFetcher() {
450public Object createService(ContextImpl ctx) {
451IBinder b = ServiceManager.getService(WIFI_SERVICE);
452IWifiManager service = IWifiManager.Stub.asInterface(b);
453returnnew WifiManager(service, ctx.mMainThread.getHandler());
454}});
In WifiSettings.java
final List<ScanResult> results = mWifiManager.getScanResults(); //同步操作
if (results != null) {
for (ScanResult result : results) {
// Ignore hidden and ad-hoc networks.
if (result.SSID == null || result.SSID.length() == 0 || result.capabilities.contains("[IBSS]")) {
continue;
}
if (result.SSID == null || result.SSID.length() == 0 ) {
continue;
}
boolean found = false;
for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
if (accessPoint.update(result))
found = true;
}
if (!found) {
AccessPoint accessPoint = new AccessPoint(getActivity(), result);
accessPoints.add(accessPoint);
apMap.put(accessPoint.ssid, accessPoint);
}
}
}
private void updateAccessPoints() {
final int wifiState = mWifiManager.getWifiState();
switch (wifiState) {
case WifiManager.WIFI_STATE_ENABLED:
// AccessPoints are automatically sorted with TreeSet.
final Collection<AccessPoint> accessPoints = constructAccessPoints();
getPreferenceScreen().removeAll();
if (mInXlSetupWizard) {
((WifiSettingsForSetupWizardXL)getActivity()).onAccessPointsUpdated(
getPreferenceScreen(), accessPoints);
} else {
for (AccessPoint accessPoint : accessPoints) {
// When WAPI is not customized to be on all
// WAPI APs will be invisible
if (accessPoint.isVisible()) {
getPreferenceScreen().addPreference(accessPoint);
}
}
}
break;
case WifiManager.WIFI_STATE_ENABLING:
getPreferenceScreen().removeAll();
break;
case WifiManager.WIFI_STATE_DISABLING:
addMessagePreference(R.string.wifi_stopping);
break;
case WifiManager.WIFI_STATE_DISABLED:
addMessagePreference(R.string.wifi_empty_list_wifi_off);
break;
}
}
Scanner使用定时器,周期性向WifiService请求扫描,相关代码如下。
private class Scanner extends Handler {
private int mRetry = 0;
void resume() {
if (!hasMessages(0)) {
sendEmptyMessage(0);
}
}
void forceScan() {
removeMessages(0);
sendEmptyMessage(0);
}
void pause() {
mRetry = 0;
removeMessages(0);
}
@Override
public void handleMessage(Message message) {
if (mWifiManager.startScanActive()) {
mRetry = 0;
} else if (++mRetry >= 3) {
mRetry = 0;
Toast.makeText(getActivity(), R.string.wifi_fail_to_scan,
Toast.LENGTH_LONG).show();
return;
}
sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
}
}
几个重要操作的控制流:
WifiSettings=>WifiManager::connect(…)
Scanner=>WifiManager:: startScanActive()
WifiEnabler=> WifiManager:: setWifienabled() ||||=>WifiService::setWifiEnabled()=>WifiStateMachine ::setWifiEnabled()
总之,发出SCAN或CONNECT的异步命令,等待事件通知做界面响应。主要就是不停的AP列表、信号强度刷新。其余命令是同步命令。
连接过程中显示的字符串
In /packages/apps/Settings/res/values/arrays.xml
223<!-- Wi-Fi settings -->
224
225<!-- Match this with the order of NetworkInfo.DetailedState. --> <skip />
226<!-- Wi-Fi settings. The status messages when the network is unknown. -->
227<string-array name="wifi_status">
228<!-- Status message of Wi-Fi when it is idle. -->
229<item></item>
230<!-- Status message of Wi-Fi when it is scanning. -->
231<item>Scanning\u2026</item>
232<!-- Status message of Wi-Fi when it is connecting. -->
233<item>Connecting\u2026</item>
234<!-- Status message of Wi-Fi when it is authenticating. -->
235<item>Authenticating\u2026</item>
236<!-- Status message of Wi-Fi when it is obtaining IP address. -->
237<item>Obtaining IP address\u2026</item>
238<!-- Status message of Wi-Fi when it is connected. -->
239<item>Connected</item>
240<!-- Status message of Wi-Fi when it is suspended. -->
241<item>Suspended</item>
242<!-- Status message of Wi-Fi when it is disconnecting. -->
243<item>Disconnecting\u2026</item>
244<!-- Status message of Wi-Fi when it is disconnected. -->
245<item>Disconnected</item>
246<!-- Status message of Wi-Fi when it is a failure. -->
247<item>Unsuccessful</item>
248</string-array>
WifiService Part structure
In WifiService.java
public class WifiService extends IWifiManager.Stub {};
WifiService线程的启动如下
In SystemServer.java
384try {
385Slog.i(TAG, "Wi-Fi P2pService");
386wifiP2p = new WifiP2pService(context);
387ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p);
388} catch (Throwable e) {
389reportWtf("starting Wi-Fi P2pService", e);
390}
391
392try {
393Slog.i(TAG, "Wi-Fi Service");
394wifi = new WifiService(context);
395ServiceManager.addService(Context.WIFI_SERVICE, wifi);
396} catch (Throwable e) {
397reportWtf("starting Wi-Fi Service", e);
398}
WifiService的构造函数本质是启动了一个带有消息队列的线程做WifiService,两个Handler attach到该消息队列上。
428HandlerThread wifiThread = new HandlerThread("WifiService");
429wifiThread.start();
430mAsyncServiceHandler = new AsyncServiceHandler(wifiThread.getLooper());
431mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
WifiSerivce作为一个service,WifiService.java在frameworks/base/services/java/com/android/server/目录下。但其实现使用的WifiStateMachine在frameworks/base/wifi/java/android/net/wifi/目录下。
WifiStateMachine状态机使用WifiNative wpa_ctrl和wpa_supplicant通讯, WifiMonitor监听WifiNative的异步消息。客户端传来的命令和WifiMonitor监听到的响应汇入WifiStateMachine的消息队列,驱动WifiStateMachine转动起来。
WifiStateMachine的方法中同步的带有’sync’字样,异步的是直接发送消息,通过WifiMonitor异步收集结果,WifiMonitor就是个ReceiverThread加消息协议转换。WifiMonitor在使用unix domain socket ctrl interface时是poll在socket上,有wpa_supplicant发回的数据时,recv。
In WifiStateMachine.java
680public void setWifiEnabled(boolean enable) {
681mLastEnableUid.set(Binder.getCallingUid());
682if (enable) {
683/* Argument is the state that is entered prior to load */
684sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
685sendMessage(CMD_START_SUPPLICANT);
686} else {
687sendMessage(CMD_STOP_SUPPLICANT);
688/* Argument is the state that is entered upon success */
689sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0));
690}
691}
In WifiStateMachine.java
553public WifiStateMachine(Context context, String wlanInterface) {
649if (DBG) setDbg(true);
650
651//start the state machine
652start();
653}
2024class InitialState extends State {
2025@Override
2026//TODO: could move logging into a common class
2027public void enter() {
2028if (DBG) log(getName() + "\n");
2029// [31-8] Reserved for future use
2030// [7 - 0] HSM state change
2031// 50021 wifi_state_changed (custom|1|5)
2032EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
2033
2034if (WifiNative.isDriverLoaded()) {
2035transitionTo(mDriverLoadedState);
2036}
2037else {
2038transitionTo(mDriverUnloadedState);
2039}
2040
2041//Connect to WifiP2pService
2042mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);
2043mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
2044
2045/* IPv6 is disabled at boot time and is controlled by framework
2046* to be enabled only as long as we are connected to an access point
2047*
2048* This fixes issues, a few being:
2049* - IPv6 addresses and routes stick around after disconnection
2050* - When connected, the kernel is unaware and can fail to start IPv6 negotiation
2051* - The kernel sometimes starts autoconfiguration when 802.1x is not complete
2052*/
2053try {
2054mNwService.disableIpv6(mInterfaceName);
2055} catch (RemoteException re) {
2056loge("Failed to disable IPv6: " + re);
2057} catch (IllegalStateException e) {
2058loge("Failed to disable IPv6: " + e);
2059}
2060}
2061}
2276class DriverUnloadedState extends State {
2277@Override
2278public void enter() {
2279if (DBG) log(getName() + "\n");
2280EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
2281}
2282@Override
2283public boolean processMessage(Message message) {
2284if (DBG) log(getName() + message.toString() + "\n");
2285switch (message.what) {
2286case CMD_LOAD_DRIVER:
2287mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
2288transitionTo(mWaitForP2pDisableState);
2289break;
2290case WifiP2pService.P2P_ENABLE_PENDING:
2291mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
2292break;
2293default:
2294return NOT_HANDLED;
2295}
2296EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
2297return HANDLED;
2298}
2299}
WifiP2pService.java会P2p的各状态下对WIFI_ENABLE_PENDING进行处理,同时WifiStateMachine进入等待p2p结束的状态。
3542class WaitForP2pDisableState extends State {
3543private int mSavedArg;
3544@Override
3545public void enter() {
3546if (DBG) log(getName() + "\n");
3547EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
3548
3549//Preserve the argument arg1 that has information used in DriverLoadingState
3550mSavedArg = getCurrentMessage().arg1;
3551}
3552@Override
3553public boolean processMessage(Message message) {
3554if (DBG) log(getName() + message.toString() + "\n");
3555switch(message.what) {
3556case WifiP2pService.WIFI_ENABLE_PROCEED:
3557//restore argument from original message (CMD_LOAD_DRIVER)
3558message.arg1 = mSavedArg;
3559transitionTo(mDriverLoadingState);
3560break;
}
}
收到P2pManager传来的WIFI_ENABLE_PROCEED,转到DriverLoadingState,开始加载driver。
2063class DriverLoadingState extends State {
2064@Override
2065public void enter() {
2066if (DBG) log(getName() + "\n");
2067EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
2068
2069final Message message = new Message();
2070message.copyFrom(getCurrentMessage());
2071/* TODO: add a timeout to fail when driver load is hung.
2072* Similarly for driver unload.
2073*/
2074new Thread(new Runnable() {
2075public void run() {
2076mWakeLock.acquire();
2077//enabling state
2078switch(message.arg1) {
2079case WIFI_STATE_ENABLING:
2080setWifiState(WIFI_STATE_ENABLING);
2081break;
2082case WIFI_AP_STATE_ENABLING:
2083setWifiApState(WIFI_AP_STATE_ENABLING);
2084break;
2085}
2086
2087if(WifiNative.loadDriver()) {
2088if (DBG) log("Driver load successful");
2089sendMessage(CMD_LOAD_DRIVER_SUCCESS);
2090} else {
2091loge("Failed to load driver!");
2092switch(message.arg1) {
2093case WIFI_STATE_ENABLING:
2094setWifiState(WIFI_STATE_UNKNOWN);
2095break;
2096case WIFI_AP_STATE_ENABLING:
2097setWifiApState(WIFI_AP_STATE_FAILED);
2098break;
2099}
2100sendMessage(CMD_LOAD_DRIVER_FAILURE);
2101}
2102mWakeLock.release();
2103}
2104}).start();
2105}
2106
2107@Override
2108public boolean processMessage(Message message) {
2109if (DBG) log(getName() + message.toString() + "\n");
2110switch (message.what) {
2111case CMD_LOAD_DRIVER_SUCCESS:
2112transitionTo(mDriverLoadedState);
2113break;
2114case CMD_LOAD_DRIVER_FAILURE:
2115transitionTo(mDriverFailedState);
2116break;
2117case CMD_LOAD_DRIVER:
2118case CMD_UNLOAD_DRIVER:
2119case CMD_START_SUPPLICANT:
2120case CMD_STOP_SUPPLICANT:
2121case CMD_START_AP:
2122case CMD_STOP_AP:
2123case CMD_START_DRIVER:
2124case CMD_STOP_DRIVER:
2125case CMD_SET_SCAN_MODE:
2126case CMD_SET_SCAN_TYPE:
2127case CMD_SET_HIGH_PERF_MODE:
2128case CMD_SET_COUNTRY_CODE:
2129case CMD_SET_FREQUENCY_BAND:
2130case CMD_START_PACKET_FILTERING:
2131case CMD_STOP_PACKET_FILTERING:
2132deferMessage(message);
2133break;
2134default:
2135return NOT_HANDLED;
2136}
2137EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
2138return HANDLED;
2139}
2140}
加载驱动成功会进入DriverLoadedState状态,在该状态下继续下一条加载wifi soc固件和启动wpa_supplicant的处理。
2142class DriverLoadedState extends State {
2143@Override
2144public void enter() {
2145if (DBG) log(getName() + "\n");
2146EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
2147}
2148@Override
2149public boolean processMessage(Message message) {
2150if (DBG) log(getName() + message.toString() + "\n");
2151switch(message.what) {
2152case CMD_UNLOAD_DRIVER:
2153transitionTo(mDriverUnloadingState);
2154break;
2155case CMD_START_SUPPLICANT:
2156try {
2157mNwService.wifiFirmwareReload(mInterfaceName, "STA");
2158} catch (Exception e) {
2159loge("Failed to reload STA firmware " + e);
2160// continue
2161}
2162try {
2163//A runtime crash can leave the interface up and
2164//this affects connectivity when supplicant starts up.
2165//Ensure interface is down before a supplicant start.
2166mNwService.setInterfaceDown(mInterfaceName);
2167//Set privacy extensions
2168mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
2169} catch (RemoteException re) {
2170loge("Unable to change interface settings: " + re);
2171} catch (IllegalStateException ie) {
2172loge("Unable to change interface settings: " + ie);
2173}
2174
2175if(WifiNative.startSupplicant()) {
2176if (DBG) log("Supplicant start successful");
2177mWifiMonitor.startMonitoring();
2178transitionTo(mSupplicantStartingState);
2179} else {
2180loge("Failed to start supplicant!");
2181sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
2182}
2183break;
2184case CMD_START_AP:
2185transitionTo(mSoftApStartingState);
2186break;
2187default:
2188return NOT_HANDLED;
2189}
2190EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
2191return HANDLED;
2192}
2193}
2315class SupplicantStartingState extends State {
2316@Override
2317public void enter() {
2318if (DBG) log(getName() + "\n");
2319EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
2320}
2321@Override
2322public boolean processMessage(Message message) {
2323if (DBG) log(getName() + message.toString() + "\n");
2324switch(message.what) {
2325case WifiMonitor.SUP_CONNECTION_EVENT:
2326if (DBG) log("Supplicant connection established");
2327WifiNative.setP2pDisable(1);
2328setWifiState(WIFI_STATE_ENABLED);
2329mSupplicantRestartCount = 0;
2330/* Reset the supplicant state to indicate the supplicant
2331* state is not known at this time */
2332mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
2333mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE);
2334/* Initialize data structures */
2335mLastBssid = null;
2336mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
2337mLastSignalLevel = -1;
2338
2339mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand());
2340
2341WifiConfigStore.initialize(mContext);
2342
2343sendSupplicantConnectionChangedBroadcast(true);
2344transitionTo(mDriverStartedState);
2345break;
2346case WifiMonitor.SUP_DISCONNECTION_EVENT:
2347if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
2348loge("Failed to setup control channel, restart supplicant");
2349WifiNative.killSupplicant();
2350transitionTo(mDriverLoadedState);
2351sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
2352} else {
2353loge("Failed " + mSupplicantRestartCount +
2354" times to start supplicant, unload driver");
2355mSupplicantRestartCount = 0;
2356transitionTo(mDriverLoadedState);
2357sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
2358}
2359break;
2360case CMD_LOAD_DRIVER:
2361case CMD_UNLOAD_DRIVER:
2362case CMD_START_SUPPLICANT:
2363case CMD_STOP_SUPPLICANT:
2364case CMD_START_AP:
2365case CMD_STOP_AP:
2366case CMD_START_DRIVER:
2367case CMD_STOP_DRIVER:
2368case CMD_SET_SCAN_MODE:
2369case CMD_SET_SCAN_TYPE:
2370case CMD_SET_HIGH_PERF_MODE:
2371case CMD_SET_COUNTRY_CODE:
2372case CMD_SET_FREQUENCY_BAND:
2373case CMD_START_PACKET_FILTERING:
2374case CMD_STOP_PACKET_FILTERING:
2375deferMessage(message);
2376break;
2377default:
2378return NOT_HANDLED;
2379}
2380EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
2381return HANDLED;
2382}
2383}
2384
2385class SupplicantStartedState extends State {
2386@Override
2387public void enter() {
2388if (DBG) log(getName() + "\n");
2389EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
2390/* Initialize for connect mode operation at start */
2391mIsScanMode = false;
2392/* Wifi is available as long as we have a connection to supplicant */
2393mNetworkInfo.setIsAvailable(true);
2394/* Set scan interval */
2395long supplicantScanIntervalMs = Settings.Secure.getLong(mContext.getContentResolver(),
2396Settings.Secure.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
2397mDefaultSupplicantScanIntervalMs);
2398WifiNative.setScanIntervalCommand((int)supplicantScanIntervalMs / 1000);
2399}
2400@Override
2401public boolean processMessage(Message message) {
2402if (DBG) log(getName() + message.toString() + "\n");
2403WifiConfiguration config;
2404boolean eventLoggingEnabled = true;
2405switch(message.what) {
2406case CMD_STOP_SUPPLICANT:/* Supplicant stopped by user */
2407transitionTo(mSupplicantStoppingState);
2408break;
2409case WifiMonitor.SUP_DISCONNECTION_EVENT:/* Supplicant connection lost */
2410loge("Connection lost, restart supplicant");
2411WifiNative.killSupplicant();
2412WifiNative.closeSupplicantConnection();
2413mNetworkInfo.setIsAvailable(false);
2414handleNetworkDisconnect();
2415sendSupplicantConnectionChangedBroadcast(false);
2416mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
2417mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE);
2418transitionTo(mDriverLoadedState);
2419sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
2420break;
2421case WifiMonitor.SCAN_RESULTS_EVENT:
2422eventLoggingEnabled = false;
2423setScanResults(WifiNative.scanResultsCommand());
2424sendScanResultsAvailableBroadcast();
2425mScanResultIsPending = false;
2426break;
2427case CMD_PING_SUPPLICANT:
2428boolean ok = WifiNative.pingCommand();
2429mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
2430break;
2431case CMD_ADD_OR_UPDATE_NETWORK:
2432config = (WifiConfiguration) message.obj;
2433mReplyChannel.replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK,
2434WifiConfigStore.addOrUpdateNetwork(config));
2435break;
2436case CMD_REMOVE_NETWORK:
2437ok = WifiConfigStore.removeNetwork(message.arg1);
2438mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
2439break;
2440case CMD_ENABLE_NETWORK:
2441ok = WifiConfigStore.enableNetwork(message.arg1, message.arg2 == 1);
2442mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
2443break;
2444case CMD_ENABLE_ALL_NETWORKS:
2445long time =android.os.SystemClock.elapsedRealtime();
2446if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) {
2447WifiConfigStore.enableAllNetworks();
2448mLastEnableAllNetworksTime = time;
2449}
2450break;
2451case CMD_DISABLE_NETWORK:
2452ok = WifiConfigStore.disableNetwork(message.arg1, message.arg2);
2453mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
2454break;
2455case CMD_BLACKLIST_NETWORK:
2456WifiNative.addToBlacklistCommand((String)message.obj);
2457break;
2458case CMD_CLEAR_BLACKLIST:
2459WifiNative.clearBlacklistCommand();
2460break;
2461case CMD_SAVE_CONFIG:
2462ok = WifiConfigStore.saveConfig();
2463mReplyChannel.replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE);
2464
2465// Inform the backup manager about a data change
2466IBackupManager ibm = IBackupManager.Stub.asInterface(
2467ServiceManager.getService(Context.BACKUP_SERVICE));
2468if (ibm != null) {
2469try {
2470ibm.dataChanged("com.android.providers.settings");
2471} catch (Exception e) {
2472// Try again later
2473}
2474}
2475break;
2476/* Cannot start soft AP while in client mode */
2477case CMD_START_AP:
2478loge("Failed to start soft AP with a running supplicant");
2479setWifiApState(WIFI_AP_STATE_FAILED);
2480break;
2481case CMD_SET_SCAN_MODE:
2482mIsScanMode = (message.arg1 == SCAN_ONLY_MODE);
2483break;
2484case CMD_SAVE_NETWORK:
2485config = (WifiConfiguration) message.obj;
2486WifiConfigStore.saveNetwork(config);
2487break;
2488case CMD_FORGET_NETWORK:
2489WifiConfigStore.forgetNetwork(message.arg1);
2490break;
2491default:
2492return NOT_HANDLED;
2493}
2494if (eventLoggingEnabled) {
2495EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
2496}
2497return HANDLED;
2498}
2499
2500@Override
2501public void exit() {
2502mNetworkInfo.setIsAvailable(false);
2503}
2504}
233private class AsyncServiceHandler extends Handler {
234
235AsyncServiceHandler(android.os.Looper looper) {
236super(looper);
237}
238
239@Override
240public void handleMessage(Message msg) {
241switch (msg.what) {
242case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
243if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
244Slog.d(TAG, "New client listening to asynchronous messages");
245mClients.add((AsyncChannel) msg.obj);
246} else {
247Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
248}
249break;
250}
251case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
252if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
253Slog.d(TAG, "Send failed, client connection lost");
254} else {
255Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
256}
257mClients.remove((AsyncChannel) msg.obj);
258break;
259}
260case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
261AsyncChannel ac = new AsyncChannel();
262ac.connect(mContext, this, msg.replyTo);
263break;
264}
265case WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL: {
266mEnableTrafficStatsPoll = (msg.arg1 == 1);
267mTrafficStatsPollToken++;
268if (mEnableTrafficStatsPoll) {
269notifyOnDataActivity();
270sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL,
271mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS);
272}
273break;
274}
275case WifiManager.CMD_TRAFFIC_STATS_POLL: {
276if (msg.arg1 == mTrafficStatsPollToken) {
277notifyOnDataActivity();
278sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL,
279mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS);
280}
281break;
282}
283case WifiManager.CMD_CONNECT_NETWORK: {
284if (msg.obj != null) {
285mWifiStateMachine.connectNetwork((WifiConfiguration)msg.obj);
286} else {
287mWifiStateMachine.connectNetwork(msg.arg1);
288}
289break;
290}
291case WifiManager.CMD_SAVE_NETWORK: {
292mWifiStateMachine.saveNetwork((WifiConfiguration)msg.obj);
293break;
294}
295case WifiManager.CMD_FORGET_NETWORK: {
296mWifiStateMachine.forgetNetwork(msg.arg1);
297break;
298}
299case WifiManager.CMD_START_WPS: {
300//replyTo has the original source
301mWifiStateMachine.startWps(msg.replyTo, (WpsInfo)msg.obj);
302break;
303}
304case WifiManager.CMD_DISABLE_NETWORK: {
305mWifiStateMachine.disableNetwork(msg.replyTo, msg.arg1, msg.arg2);
306break;
307}
308default: {
309Slog.d(TAG, "WifiServicehandler.handleMessage ignoring msg=" + msg);
310break;
311}
312}
313}
314}
调用WifiStateMachine的connectNetwork方法。
935public void connectNetwork(int netId) {
936sendMessage(obtainMessage(CMD_CONNECT_NETWORK, netId, 0));
937}
938
939public void connectNetwork(WifiConfiguration wifiConfig) {
940/* arg1 is used to indicate netId, force a netId value of
941* WifiConfiguration.INVALID_NETWORK_ID when we are passing
942* a configuration since the default value of 0 is a valid netId
943*/
944sendMessage(obtainMessage(CMD_CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
9450, wifiConfig));
946}
在ConnectedState时,新选择network,连接,并且在收到连接好前转到disconnectState
2969case CMD_CONNECT_NETWORK:
2970int netId = message.arg1;
2971WifiConfiguration config = (WifiConfiguration) message.obj;
2972
2973/* We connect to a specific network by issuing a select
2974* to the WifiConfigStore. This enables the network,
2975* while disabling all other networks in the supplicant.
2976* Disabling a connected network will cause a disconnection
2977* from the network. A reconnectCommand() will then initiate
2978* a connection to the enabled network.
2979*/
2980if (config != null) {
2981netId = WifiConfigStore.selectNetwork(config);
2982} else {
2983WifiConfigStore.selectNetwork(netId);
2984}
2985
2986/* The state tracker handles enabling networks upon completion/failure */
2987mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK);
2988
2989WifiNative.reconnectCommand();
2990mLastExplicitNetworkId = netId;
2991mLastNetworkChoiceTime= SystemClock.elapsedRealtime();
2992mNextWifiActionExplicit = true;
2993if (DBG) log("Setting wifi connect explicit for netid " + netId);
2994/* Expect a disconnection from the old connection */
2995transitionTo(mDisconnectingState);
2996break;
SupplicantStateTracker.java收到CMD_CONNECT_NETWORK消息后追踪状态。主要是在reconnectCommand中做的连接。
152
153class DefaultState extends State {
154@Override
155public void enter() {
156if (DBG) Log.d(TAG, getName() + "\n");
157}
158@Override
159public boolean processMessage(Message message) {
160if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
161switch (message.what) {
162case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
163mAuthenticationFailuresCount++;
164mAuthFailureInSupplicantBroadcast = true;
165break;
166case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
167StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
168SupplicantState state = stateChangeResult.state;
169sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
170mAuthFailureInSupplicantBroadcast = false;
171transitionOnSupplicantStateChange(stateChangeResult);
172break;
173case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
174transitionTo(mUninitializedState);
175break;
176case WifiStateMachine.CMD_CONNECT_NETWORK:
177mNetworksDisabledDuringConnect = true;
178break;
179default:
180Log.e(TAG, "Ignoring " + message);
181break;
182}
183return HANDLED;
184}
185}
WifiNative.java
104public native static boolean reconnectCommand();
android_net_wifi_Wifi.cpp
603 { "reconnectCommand", "()Z", (void *)android_net_wifi_reconnectCommand },
WifiNative.java中使用reconnectCommand方法时没有检查返回值,所以消息估计是异步传回。
static jboolean doBooleanCommand(const char* expect, const char* fmt, ...)
static int doCommand(const char *cmd, char *replybuf, int replybuflen)
call int wifi_command(const char *command, char *reply, size_t *reply_len)@ wifi_bcm.c
wpa_supplicant的扫描结果中有IBSS WEP,在Java层被过滤掉。
android_net_wifi_Wifi.cpp
120static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
121{
122return (jboolean)(::wifi_load_driver() == 0);
123}
wifi_bcm.c
wifi_bcm.c有设置KMGT update_ctrl_interface ,就是从config file里面找ctrl_interface=wlan0这项,生成unix domain socket的监听端口文件名。wlan0时,系统会生成/dev/socket/wpa_wlan0;是目录的时候,可能在该目录下生成一个什么名称的文件。
875int wifi_command(const char *command, char *reply, size_t *reply_len)
876{
877return wifi_send_command(ctrl_conn, command, reply, reply_len);
878}
发送命令到wpa_supplicant的监听socket上,该socket的recv函数是wpa_supplicant_ctrl_iface_receive,在wpa_supplicant的初始化过程中注册
main() => wpa_supplicant_add_iface=> wpa_supplicant_init_iface => wpa_supplicant_ctrl_iface_init => eloop_register_read_sock.
wpa_supplicant_ctrl_iface_receive => wpa_supplicant_ctrl_iface_process
3286} else if (os_strcmp(buf, "RECONNECT") == 0) {
3287if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3288reply_len = -1;
3289else if (wpa_s->disconnected) {
3290wpa_s->disconnected = 0;
3291wpa_s->reassociate = 1;
3292wpa_supplicant_req_scan(wpa_s, 0, 0);
3293}
3521} else if (os_strcmp(buf, "SCAN") == 0) {
3522if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3523reply_len = -1;
3524else {
3525if (!wpa_s->scanning &&
3526((wpa_s->wpa_state <= WPA_SCANNING) ||
3527(wpa_s->wpa_state == WPA_COMPLETED))) {
3528wpa_s->scan_req = 2;
3529wpa_supplicant_req_scan(wpa_s, 0, 0);
3530} else {
3531wpa_printf(MSG_DEBUG, "Ongoing scan action - "
3532"reject new request");
3533reply_len = os_snprintf(reply, reply_size,
3534"FAIL-BUSY\n");
3535}
3536}
3537} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
3538reply_len = wpa_supplicant_ctrl_iface_scan_results(
3539wpa_s, reply, reply_size);
3540} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
3541if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
3542reply_len = -1;
3543} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
3544if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
3545reply_len = -1;
3546} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
3547if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
3548reply_len = -1;
3549} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
3550reply_len = wpa_supplicant_ctrl_iface_add_network(
3551wpa_s, reply, reply_size);
3552} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
3553if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
3554reply_len = -1;
3555} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
3556if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
3557reply_len = -1;
3558} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
3559reply_len = wpa_supplicant_ctrl_iface_get_network(
3560wpa_s, buf + 12, reply, reply_size);
3561#ifndef CONFIG_NO_CONFIG_WRITE
3562} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
3563if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
3564reply_len = -1;
3565#endif /* CONFIG_NO_CONFIG_WRITE */
3566} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
3567reply_len = wpa_supplicant_ctrl_iface_get_capability(
3568wpa_s, buf + 15, reply, reply_size);
3569} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
3570if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
3571reply_len = -1;
3572} else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
hardware/libhardware_legacy/wifi/Android.mk
3LOCAL_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
4LOCAL_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_PREFIX=\"wpa_ctrl_\"
/data/misc/wifi/sockets是使用wpa_cli库接口建立unix domain socket时,本地文件名。这两个宏构成如/data/misc/wifi/sockets/ wpa_ctrl_pid-nn的文件名,就是unix domain socket的文件名。
目标文件名是/dev/socket/wpa_wlan0,是socket的另一端,这个是由wpa_supplicant打开的。参见init.Manufacture.rc。wpa_cli去连接这个服务端口。
使用单独的wpa_cli端时,如下使用
wpa_cli -p /dev/socket/ -i wpa_wlan0
单独的wpa_cli会新建两个unix domain socket的两个local文件名。
wpa_ctrl_11762-1
wpa_ctrl_11762-2
如果wpa_supplicant以logger输出时,wpa_cli会得到消息输出。
9738 log0:00 /system/bin/logwrapper /system/bin/wpa_supplicant -iwlan0 -puse_p2p_group_interface=1 -Dnl80211 -iwlan0 -c/data/misc/wifi/wpa_supplicant.conf -ddd
9740 wifi0:23 /system/bin/wpa_supplicant -iwlan0 -puse_p2p_group_interface=1 -Dnl80211 -iwlan0 -c/data/misc/wifi/wpa_supplicant.conf -ddd
wifi驱动可能是
#define WIFI_DRIVER_MODULE_PATH "/system/lib/modules/wlan.ko"
可能是
#WIFI_DRIVER_MODULE_PATH := "/system/etc/bcm4330/dhd.ko"
insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG)
也可能是builtIn的。in wifi_bcm.c
LOGI("Using BuildIn WiFi driver");
property_set(DRIVER_PROP_NAME, "ok");
加载wpa_supplicant
property_get("wifi.interface", iface, WIFI_TEST_INTERFACE);
property_get("persist.wpa_supplicant.debug", supp_debug, "false");
if (strcmp(supp_debug, "true") == 0) {
SLOGI("persist.wpa_supplicant.debug property true");
snprintf(daemon_cmd, PROPERTY_VALUE_MAX, "%s:-i%s -c%s -ddd", SUPPLICANT_NAME, iface, config_file);
} else {
SLOGI("persist.wpa_supplicant.debug property false");
snprintf(daemon_cmd, PROPERTY_VALUE_MAX, "%s:-i%s -c%s", SUPPLICANT_NAME, iface, config_file);
}
property_set("ctl.start", daemon_cmd);
由driver扫描完后发出 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
2155case EVENT_SCAN_RESULTS:
2156wpa_supplicant_event_scan_results(wpa_s, data);
2157break;
wpa_supplicant_event_scan_results
_wpa_supplicant_event_scan_results
wpa_supplicant_pick_network
wpa_supplicant_select_bss
wpa_scan_res_match
现在的是match之后,下一个是什么过程。要找到:从Connect命令后找,启动搜索,搜索结果,configed匹配到?
连接前启动扫描,扫描结果匹配后,自然是连接。就从_wpa_supplicant_event_scan_results在pick netwoerk之后看。
if (selected) {
int skip;
skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid, scan_res);
wpa_scan_results_free(scan_res);
if (skip)
return 0;
wpa_supplicant_connect(wpa_s, selected, ssid);
wpa_supplicant_rsn_preauth_scan_results(wpa_s);
}
wpa_supplicant_connect=>wpa_supplicant_associate
@ssid: wpa_ssid structure for a configured network or %NULL for any network
wpa_supplicant_ctrl_iface_select_network => wpa_supplicant_select_network =>wpa_supplicant_req_scan(wpa_s, 0, 0);
wpa_supplicant_enable_network - Mark a configured network as enabled
@ssid: wpa_ssid structure for a configured network or %NULL
wpa_supplicant_ctrl_iface_enable_network => wpa_supplicant_enable_network =>wpa_supplicant_req_scan(wpa_s, 0, 0);
当扫描时wpa_supplicant_scan with ap_scan==0 => wpa_supplicant_gen_assoc_event
32static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
33{
34struct wpa_ssid *ssid;
35union wpa_event_data data;
36
37ssid = wpa_supplicant_get_ssid(wpa_s);
38if (ssid == NULL)
39return;
40
41if (wpa_s->current_ssid == NULL) {
42wpa_s->current_ssid = ssid;
43if (wpa_s->current_ssid != NULL)
44wpas_notify_network_changed(wpa_s);
45}
46wpa_supplicant_initiate_eapol(wpa_s);
47wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
48"network - generating associated event");
49os_memset(&data, 0, sizeof(data));
50wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
51}
或者当连接bss后,
wpa_driver_nl80211_event_receive=> process_event() => mlme_event_join_ibss() => wpa_supplicant_event(drv->ctx,EVENT_ASSOC, NULL);
在wpa_driver_nl80211_init_nl中,wpa_driver_nl80211_event_receive注册到netlink socket的读处理上。
eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event),
wpa_driver_nl80211_event_receive, drv,
drv->nl_handle_event);
或者当INFRA时,
直接wpa_driver_nl80211_connect发送NL80211_CMD_CONNECT,会收到NL80211_CMD_CONNECT响应,用mlme_event_connect=>wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);处理
好像是用来做AUTH+ASSOCIATE阶段的。
case EVENT_ASSOC: wpa_supplicant_event_assoc(wpa_s, data);
driver可以找到是kernel/drivers/net/wireless/bcmdhd/wl_cfg80211.c
按照driver的要求打包数据。
wpa_supplicant_associate是连接和验证的入口。
wpa_supplicant_associate
calls => wpa_drv_associate
calls => wpa_driver_nl80211_associate when drvier_nl80211 is used.
calls => wpa_driver_nl80211_ibss for IBSS mode.
wpa_driver_nl80211_ibss首先将驱动和固件设置到IBSS工作模式,然后发送JOIN_IBSS命令。
4709static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
4710struct wpa_driver_associate_params *params)
4711{
4712struct nl_msg *msg;
4713int ret = -1;
4714int count = 0;
4715
4716wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
4717
4718if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) {
4719wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
4720"IBSS mode");
4721return -1;
4722}
4723
4724retry:
4725msg = nlmsg_alloc();
4726if (!msg)
4727return -1;
4728
4729genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
4730NL80211_CMD_JOIN_IBSS, 0);
4731NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4732
4733if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
4734goto nla_put_failure;
4735
4736wpa_hexdump_ascii(MSG_DEBUG, "* SSID",
4737params->ssid, params->ssid_len);
4738NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
4739params->ssid);
4740os_memcpy(drv->ssid, params->ssid, params->ssid_len);
4741drv->ssid_len = params->ssid_len;
4742
4743wpa_printf(MSG_DEBUG, "* freq=%d", params->freq);
4744NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
4745
4746ret = nl80211_set_conn_keys(params, msg);
4747if (ret)
4748goto nla_put_failure;
4749
4750if (params->wpa_ie) {
4751wpa_hexdump(MSG_DEBUG,
4752"* Extra IEs for Beacon/Probe Response frames",
4753params->wpa_ie, params->wpa_ie_len);
4754NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
4755params->wpa_ie);
4756}
4757
4758ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4759msg = NULL;
4760if (ret) {
4761wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
4762ret, strerror(-ret));
4763count++;
4764if (ret == -EALREADY && count == 1) {
4765wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after "
4766"forced leave");
4767nl80211_leave_ibss(drv);
4768nlmsg_free(msg);
4769goto retry;
4770}
4771
4772goto nla_put_failure;
4773}
4774ret = 0;
4775wpa_printf(MSG_DEBUG, "nl80211: Join IBSS request sent successfully");
4776
4777nla_put_failure:
4778nlmsg_free(msg);
4779return ret;
4780}
首先看设置网卡工作模式 INFRA还是ADHOC
5148static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
5149int ifindex, int mode)
5150{
5151struct nl_msg *msg;
5152int ret = -ENOBUFS;
5153
5154msg = nlmsg_alloc();
5155if (!msg)
5156return -ENOMEM;
5157
5158genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
51590,NL80211_CMD_SET_INTERFACE, 0);
5160NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
5161NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);
5162
5163ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5164if (!ret)
5165return 0;
5166nla_put_failure:
5167wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
5168" %d (%s)", ifindex, mode, ret, strerror(-ret));
5169return ret;
5170}
NL80211_CMD_SET_INTERFACE command to kernel space driver =>
static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
=>
1586if (change)
1587err =cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms);
cfg80211_change_iface instead calls =>
=> wl_cfg80211_change_virtual_iface
此处wl_cfg80211在设置到IBSS模式时没有执行,需要patch上WLC_SET_INFRA
err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
另外地,wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true)在wl_config_ifmode中也被调用,而wl_config_ifmode在wl_cfg80211_up(void *para)=>__wl_cfg80211_up中被调用。
wl_cfg80211_up只在dhd驱动的open函数dhd_open(struct net_device *net)中使用一次,用于网卡打开进行配置使用,所以iwconfig可以使能网卡IBSS模式,但是wpa_supplicant不能使能网卡IBSS模式的原因大概在此。
static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
{
s32 infra = 0;
s32 err = 0;
s32 mode = 0;
switch (iftype) {
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_WDS:
WL_ERR(("type (%d) : currently we do not support this mode\n",
iftype));
err = -EINVAL;
return err;
case NL80211_IFTYPE_ADHOC:
mode = WL_MODE_IBSS;
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
mode = WL_MODE_BSS;
infra = 1;
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
mode = WL_MODE_AP;
infra = 1;
break;
default:
err = -EINVAL;
WL_ERR(("invalid type (%d)\n", iftype));
return err;
}
infra = htod32(infra);
err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
if (unlikely(err)) {
WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
return err;
}
wl_set_mode_by_netdev(wl, ndev, mode);
return 0;
}
再看第二个步骤发送JOIN_IBSS
join_ibss in driver_nl80211.c
wpa_driver_nl80211_ibss
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
NL80211_CMD_JOIN_IBSS, 0);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
kernel/net/wireless/nl80211.c is one driver top file for JOIN_IBSS。
4330static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4331{
4332struct cfg80211_registered_device *rdev = info->user_ptr[0];
4333struct net_device *dev = info->user_ptr[1];
4334struct cfg80211_ibss_params ibss;
4335struct wiphy *wiphy;
4336struct cfg80211_cached_keys *connkeys = NULL;
4337int err;
4338
4339memset(&ibss, 0, sizeof(ibss));
4340
4341if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
4342return -EINVAL;
4343
4344if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
4345!info->attrs[NL80211_ATTR_SSID] ||
4346!nla_len(info->attrs[NL80211_ATTR_SSID]))
4347return -EINVAL;
4348
4349ibss.beacon_interval = 100;
4350
4351if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
4352ibss.beacon_interval =
4353nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
4354if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000)
4355return -EINVAL;
4356}
4357
4358if (!rdev->ops->join_ibss)
4359return -EOPNOTSUPP;
4360
4361if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
4362return -EOPNOTSUPP;//这个东西并不影响IBSS逻辑
4363
4364wiphy = &rdev->wiphy;
4365
4366if (info->attrs[NL80211_ATTR_MAC])
4367ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
4368ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
4369ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
4370
4371if (info->attrs[NL80211_ATTR_IE]) {
4372ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
4373ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
4374}
4375
4376ibss.channel = ieee80211_get_channel(wiphy,
4377nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
4378if (!ibss.channel ||
4379ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
4380ibss.channel->flags & IEEE80211_CHAN_DISABLED)
4381return -EINVAL;
4382
4383ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
4384ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
4385
4386if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
4387u8 *rates =
4388nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
4389int n_rates =
4390nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
4391struct ieee80211_supported_band *sband =
4392wiphy->bands[ibss.channel->band];
4393int err;
4394err = ieee80211_get_ratemask(sband, rates, n_rates,
4395&ibss.basic_rates);
4396if (err)
4397return err;
4398}
4399
4400if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
4401!nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
4402nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
4403return -EINVAL;
4404
4405if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
4406connkeys = nl80211_parse_connkeys(rdev,
4407info->attrs[NL80211_ATTR_KEYS]);
4408if (IS_ERR(connkeys))
4409return PTR_ERR(connkeys);
4410}
4411
4412err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
4413if (err)
4414kfree(connkeys);
4415return err;
4416}
In wl_cfg80211.c
1758static s32
1759wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1760struct cfg80211_ibss_params *params)
1761{
1762struct wl_priv *wl = wiphy_priv(wiphy);
1763struct cfg80211_bss *bss;
1764struct ieee80211_channel *chan;
1765struct wl_join_params join_params;
1766struct cfg80211_ssid ssid;
1767s32 scan_retry = 0;
1768s32 err = 0;
1769bool rollback_lock = false;
1770
1771WL_TRACE(("In\n"));
1772CHECK_SYS_UP(wl);
1773if (params->bssid) {// remove the ibss-blocking code
1774WL_ERR(("Invalid bssid\n"));
1775return -EOPNOTSUPP;
1776}
1777bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
1778if (!bss) {
1779memcpy(ssid.ssid, params->ssid, params->ssid_len);
1780ssid.ssid_len = params->ssid_len;
1781do {
1782if (unlikely
1783(__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
1784-EBUSY)) {
1785wl_delay(150);
1786} else {
1787break;
1788}
1789} while (++scan_retry < WL_SCAN_RETRY_MAX);
1790/* to allow scan_inform to propagate to cfg80211 plane */
1791if (rtnl_is_locked()) {
1792rtnl_unlock();
1793rollback_lock = true;
1794}
1795
1796/* wait 4 secons till scan done.... */
1797schedule_timeout_interruptible(4 * HZ);
1798if (rollback_lock)
1799rtnl_lock();
1800bss = cfg80211_get_ibss(wiphy, NULL,
1801params->ssid, params->ssid_len);
1802}
1803if (bss) {
1804wl->ibss_starter = false;
1805WL_DBG(("Found IBSS\n"));
1806} else {
1807wl->ibss_starter = true;
1808}
1809chan = params->channel;
1810if (chan)
1811wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
1812/*
1813* Join with specific BSSID and cached SSID
1814* If SSID is zero join based on BSSID only
1815*/
1816memset(&join_params, 0, sizeof(join_params));
1817memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
1818params->ssid_len);
1819join_params.ssid.SSID_len = htod32(params->ssid_len);
1820if (params->bssid)
1821memcpy(&join_params.params.bssid, params->bssid,
1822ETHER_ADDR_LEN);
1823else
1824memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
1825
1826err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
1827sizeof(join_params), false);
1828if (unlikely(err)) {
1829WL_ERR(("Error (%d)\n", err));
1830return err;
1831}
1832return err;
1833}
发送给dhd固件,err是0,表发送成功;
WLC_SET_SSID的结果以异步形式由固件发送回来。此时收到的WLC_E_SET_SSID的status是WLC_E_STATUS_NO_NETWORKS。
设置WLC_SET_INFRA后,修改join_ibss相关代码,可以收到WLC_E_SET_SSID with status WLC_E_STATUS_SUCCESSFUL,连接上IBSS。
驱动中在IBSS时收到的主要是WLC_E_LINK、WLC_E_JOIN和WLC_E_SET_SSID,会通过event_handler处理或通知wpa_supplicant.
wpa_driver_nl80211_event_rtm_newlink是在wpa_driver_nl80211_init中注册的
cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
wl_notify_connect_status是在wl_init_event_handler中注册的。
5255static void wl_init_event_handler(struct wl_priv *wl)
5256{
5257memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
5258
5259wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
5260wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
5261wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
5262wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
5263wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
5264wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
5265wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
5266wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
5267wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
5268wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
5269wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
5270wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
5271wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
5272wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
5273wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
5274wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
5275
5276}
以下BoardConfig.mk中的好像没用到,没有定义WIFI_DRIVER_MODULE_PATH。
device/qcom/msm7627a/BoardConfig.mk
7ifeq ($(QC_PROP),true)
8BOARD_USES_QCOM_HARDWARE := true
9DYNAMIC_SHARED_LIBV8SO := true
10BOARD_USES_ADRENO_200 := true
11HAVE_ADRENO200_SOURCE := true
12HAVE_ADRENO200_SC_SOURCE := true
13HAVE_ADRENO200_FIRMWARE := true
14BOARD_USES_QCNE := true
15USE_OPENGL_RENDERER := true
16BOARD_USE_QCOM_LLVM_CLANG_RS := true
17ifneq ($(BUILD_TINY_ANDROID), true)
18BOARD_VENDOR_QCOM_GPS_LOC_API_AMSS_VERSION := 50001
19BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE := default
20BOARD_CAMERA_LIBRARIES := libcamera
21BOARD_HAVE_BLUETOOTH := true
22BOARD_HAVE_BLUETOOTH_BCM := true
23BOARD_HAVE_QCOM_FM := false
24#BOARD_USES_GENERIC_AUDIO := true
25HOSTAPD_VERSION := VER_2_0_DEV_BCM
26BOARD_HOSTAPD_DRIVER := NL80211
27#BOARD_HAS_QCOM_WLAN := true
28BOARD_WPA_SUPPLICANT_DRIVER := NL80211
29WPA_SUPPLICANT_VERSION := VER_0_8_X_BCM
30
31#WIFI_DRIVER_MODULE_PATH := "/system/etc/bcm4330/dhd.ko"
32WIFI_DRIVER_MODULE_NAME := "dhd"
33WIFI_DRIVER_MODULE_ARG:= "firmware_path=/system/etc/bcm4330/sdio-g-pool-pno-pktfilter-keepalive-wapi-wme-p2p-idsup-idauth-sta-aoe.bin nvram_path=/system/etc/bcm4330/bcm94330wlsdgbphone.txt iface_name=wlan"
34BOARD_HOTSPOT_SAR_BACKUP := true
35
36
37#WIFI_SDIO_IF_DRIVER_MODULE_PATH := "/system/lib/modules/librasdioif.ko"
38#WIFI_SDIO_IF_DRIVER_MODULE_NAME := "librasdioif"
39#WIFI_SDIO_IF_DRIVER_MODULE_ARG:= ""
40WIFI_DRIVER_FW_PATH_PARAM := "/sys/module/bcmdhd/parameters/firmware_path"
41WIFI_DRIVER_FW_PATH_STA := "/system/etc/bcm4330/sdio_g_pool_pno_pktfilter_keepalive_wapi_wme_idsup_idauth_sta_aoe.bin"
42WIFI_DRIVER_FW_PATH_AP:= "/system/etc/bcm4330/sdio_g_pool_pno_pktfilter_keepalive_wapi_wme_idsup_idauth_apsta_aoe.bin"
43WIFI_DRIVER_FW_PATH_P2P := "/system/etc/bcm4330/sdio_g_pool_pno_pktfilter_keepalive_wapi_wme_idsup_idauth_p2p_aoe.bin"
44BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_bcmdhd
45BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_bcmdhd
46BOARD_WLAN_DEVICE := bcmdhd
47endif# !BUILD_TINY_ANDROID
其余在init.rc中
setprop wifi.interface wlan0
# Connectivity: Enable Wifi EAP SIM
setprop ro.wifi.eap_sim_enabled true
chown wifi wifi /dev/wlandev
chmod 0660 /dev/wlandev
# Create the directories used by the Wireless subsystem
mkdir /data/misc/wifi 0770 wifi wifi
mkdir /data/misc/wifi/sockets 0770 wifi wifi
mkdir /data/misc/wifi/wpa_supplicant 0770 wifi wifi
mkdir /data/misc/dhcp 0770 dhcp dhcp
chown dhcp dhcp /data/misc/dhcp
service wpa_supplicant /system/bin/logwrapper /system/bin/wpa_supplicant -iwlan0 -puse_p2p_group_interface=1 -Dnl80211
class late_start
user root
group wifi inet
socket wpa_wlan0 dgram 660 wifi wifi
disabled
oneshot
service dhcpcd_wlan0 /system/bin/dhcpcd -ABKLG
class late_start
disabled
oneshot
service qcom-sh /system/bin/sh /init.qcom.sh
class late_start
user root
oneshot
service qcom-wifi /system/bin/sh /system/etc/init.qcom.wifi.sh
class late_start
oneshot
desnt works
/system/bin/logwrapper /system/bin/wpa_supplicant -iwlan0 -puse_p2p_group_interface=1 -Dnl80211 -C/data/system/wpa_supplicant -c/data/misc/wifi/wpa_supplicant.conf