展会信息港展会大全

Patch android wifi to enable IBSS/WEP support
来源:互联网   发布日期:2015-09-28 16:07:12   浏览:10876次  

导读: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的...

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, &ether_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, &params);

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

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港