Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Patch android wifi to enable IBSS/WEP support

Patch android wifi to enable IBSS/WEP support

編輯:關於Android編程

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中。 In  wpa_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 169    public 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 174       mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 175       mWifiManager.asyncConnect(getActivity(), new WifiServiceHandler()); 176        if (savedInstanceState != null 177                && savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) { 178            mDlgEdit = savedInstanceState.getBoolean(SAVE_DIALOG_EDIT_MODE); 179            mAccessPointSavedState = savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE); 180        } 1101     public void asyncConnect(Context srcContext, Handler srcHandler) { 1102        mAsyncChannel.connect(srcContext, srcHandler, getMessenger()); 1103     } establish a half connect between WifiManager and WifiService. 1117    public void connectNetwork(WifiConfiguration config) { 1118        if (config == null) { 1119            return; 1120        } 1121        mAsyncChannel.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 485    public WifiManager(IWifiManager service, Handler handler) { 486        mService = service; 487        mHandler = handler; 488    } In ContextImpl.java        449        registerService(WIFI_SERVICE, new ServiceFetcher() { 450                public Object createService(ContextImpl ctx) { 451                   IBinder b = ServiceManager.getService(WIFI_SERVICE); 452                    IWifiManager service = IWifiManager.Stub.asInterface(b); 453                    returnnew 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 384           try { 385                Slog.i(TAG, "Wi-Fi P2pService"); 386                wifiP2p = new WifiP2pService(context); 387                ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p); 388            } catch (Throwable e) { 389                reportWtf("starting Wi-Fi P2pService", e); 390            } 391 392           try { 393                Slog.i(TAG, "Wi-Fi Service"); 394                wifi = new WifiService(context); 395                ServiceManager.addService(Context.WIFI_SERVICE, wifi); 396            } catch (Throwable e) { 397                reportWtf("starting Wi-Fi Service", e); 398            } WifiService的構造函數本質是啟動了一個帶有消息隊列的線程做WifiService,兩個Handler attach到該消息隊列上。 428        HandlerThread wifiThread = new HandlerThread("WifiService"); 429        wifiThread.start(); 430        mAsyncServiceHandler = new AsyncServiceHandler(wifiThread.getLooper()); 431        mWifiStateMachineHandler = 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 680    public void setWifiEnabled(boolean enable) { 681        mLastEnableUid.set(Binder.getCallingUid()); 682        if (enable) { 683            /* Argument is the state that is entered prior to load */ 684            sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0)); 685            sendMessage(CMD_START_SUPPLICANT); 686        } else { 687            sendMessage(CMD_STOP_SUPPLICANT); 688            /* Argument is the state that is entered upon success */ 689            sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0)); 690        } 691    }   In WifiStateMachine.java 553    public WifiStateMachine(Context context, String wlanInterface) { 649        if (DBG) setDbg(true); 650 651        //start the state machine 652        start(); 653    }   2024    class InitialState extends State { 2025        @Override 2026        //TODO: could move logging into a common class 2027        public void enter() { 2028            if (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) 2032            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2033 2034            if (WifiNative.isDriverLoaded()) { 2035                transitionTo(mDriverLoadedState); 2036            } 2037            else { 2038               transitionTo(mDriverUnloadedState); 2039            } 2040 2041            //Connect to WifiP2pService 2042            mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE); 2043            mWifiP2pChannel.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             */ 2053            try { 2054                mNwService.disableIpv6(mInterfaceName); 2055            } catch (RemoteException re) { 2056                loge("Failed to disable IPv6: " + re); 2057            } catch (IllegalStateException e) { 2058                loge("Failed to disable IPv6: " + e); 2059            } 2060        } 2061    }   2276    class DriverUnloadedState extends State { 2277        @Override 2278        public void enter() { 2279            if (DBG) log(getName() + "\n"); 2280            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2281        } 2282        @Override 2283        public boolean processMessage(Message message) { 2284            if (DBG) log(getName() + message.toString() + "\n"); 2285            switch (message.what) { 2286               case CMD_LOAD_DRIVER: 2287                   mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING); 2288                   transitionTo(mWaitForP2pDisableState); 2289                    break; 2290                case WifiP2pService.P2P_ENABLE_PENDING: 2291                    mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED); 2292                    break; 2293                default: 2294                    return NOT_HANDLED; 2295            } 2296            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2297            return HANDLED; 2298        } 2299    }   WifiP2pService.java會P2p的各狀態下對WIFI_ENABLE_PENDING進行處理,同時WifiStateMachine進入等待p2p結束的狀態。 3542    class WaitForP2pDisableState extends State { 3543        private int mSavedArg; 3544        @Override 3545        public void enter() { 3546            if (DBG) log(getName() + "\n"); 3547            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 3548 3549            //Preserve the argument arg1 that has information used in DriverLoadingState 3550            mSavedArg = getCurrentMessage().arg1; 3551        } 3552        @Override 3553        public boolean processMessage(Message message) { 3554            if (DBG) log(getName() + message.toString() + "\n"); 3555            switch(message.what) { 3556                case WifiP2pService.WIFI_ENABLE_PROCEED: 3557                    //restore argument from original message (CMD_LOAD_DRIVER) 3558                    message.arg1 = mSavedArg; 3559                   transitionTo(mDriverLoadingState); 3560                    break;      } } 收到P2pManager傳來的WIFI_ENABLE_PROCEED,轉到DriverLoadingState,開始加載driver。 2063    class DriverLoadingState extends State { 2064        @Override 2065        public void enter() { 2066            if (DBG) log(getName() + "\n"); 2067            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2068 2069            final Message message = new Message(); 2070            message.copyFrom(getCurrentMessage()); 2071            /* TODO: add a timeout to fail when driver load is hung. 2072             * Similarly for driver unload. 2073             */ 2074            new Thread(new Runnable() { 2075                public void run() { 2076                    mWakeLock.acquire(); 2077                    //enabling state 2078                    switch(message.arg1) { 2079                        case WIFI_STATE_ENABLING: 2080                            setWifiState(WIFI_STATE_ENABLING); 2081                            break; 2082                        case WIFI_AP_STATE_ENABLING: 2083                            setWifiApState(WIFI_AP_STATE_ENABLING); 2084                            break; 2085                    } 2086 2087                    if(WifiNative.loadDriver()) { 2088                        if (DBG) log("Driver load successful"); 2089                       sendMessage(CMD_LOAD_DRIVER_SUCCESS); 2090                    } else { 2091                        loge("Failed to load driver!"); 2092                        switch(message.arg1) { 2093                            case WIFI_STATE_ENABLING: 2094                                setWifiState(WIFI_STATE_UNKNOWN); 2095                                break; 2096                            case WIFI_AP_STATE_ENABLING: 2097                                setWifiApState(WIFI_AP_STATE_FAILED); 2098                                break; 2099                        } 2100                        sendMessage(CMD_LOAD_DRIVER_FAILURE); 2101                    } 2102                    mWakeLock.release(); 2103                } 2104            }).start(); 2105        } 2106 2107        @Override 2108        public boolean processMessage(Message message) { 2109            if (DBG) log(getName() + message.toString() + "\n"); 2110            switch (message.what) { 2111               case CMD_LOAD_DRIVER_SUCCESS: 2112                    transitionTo(mDriverLoadedState); 2113                    break; 2114                case CMD_LOAD_DRIVER_FAILURE: 2115                    transitionTo(mDriverFailedState); 2116                    break; 2117                case CMD_LOAD_DRIVER: 2118                case CMD_UNLOAD_DRIVER: 2119                case CMD_START_SUPPLICANT: 2120                case CMD_STOP_SUPPLICANT: 2121                case CMD_START_AP: 2122                case CMD_STOP_AP: 2123                case CMD_START_DRIVER: 2124                case CMD_STOP_DRIVER: 2125                case CMD_SET_SCAN_MODE: 2126                case CMD_SET_SCAN_TYPE: 2127                case CMD_SET_HIGH_PERF_MODE: 2128                case CMD_SET_COUNTRY_CODE: 2129                case CMD_SET_FREQUENCY_BAND: 2130                case CMD_START_PACKET_FILTERING: 2131                case CMD_STOP_PACKET_FILTERING: 2132                    deferMessage(message); 2133                    break; 2134                default: 2135                    return NOT_HANDLED; 2136            } 2137            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2138            return HANDLED; 2139        } 2140    } 加載驅動成功會進入DriverLoadedState狀態,在該狀態下繼續下一條加載wifi soc固件和啟動wpa_supplicant的處理。 2142    class DriverLoadedState extends State { 2143        @Override 2144        public void enter() { 2145            if (DBG) log(getName() + "\n"); 2146            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2147        } 2148        @Override 2149        public boolean processMessage(Message message) { 2150            if (DBG) log(getName() + message.toString() + "\n"); 2151            switch(message.what) { 2152                case CMD_UNLOAD_DRIVER: 2153                    transitionTo(mDriverUnloadingState); 2154                    break; 2155                case CMD_START_SUPPLICANT: 2156                    try { 2157                        mNwService.wifiFirmwareReload(mInterfaceName, "STA"); 2158                    } catch (Exception e) { 2159                        loge("Failed to reload STA firmware " + e); 2160                        // continue 2161                    } 2162                   try { 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. 2166                       mNwService.setInterfaceDown(mInterfaceName); 2167                        //Set privacy extensions 2168                        mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); 2169                    } catch (RemoteException re) { 2170                        loge("Unable to change interface settings: " + re); 2171                    } catch (IllegalStateException ie) { 2172                        loge("Unable to change interface settings: " + ie); 2173                    } 2174 2175                    if(WifiNative.startSupplicant()) { 2176                        if (DBG) log("Supplicant start successful"); 2177                        mWifiMonitor.startMonitoring(); 2178                        transitionTo(mSupplicantStartingState); 2179                    } else { 2180                        loge("Failed to start supplicant!"); 2181                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0)); 2182                    } 2183                    break; 2184                case CMD_START_AP: 2185                    transitionTo(mSoftApStartingState); 2186                    break; 2187                default: 2188                    return NOT_HANDLED; 2189            } 2190            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2191            return HANDLED; 2192        } 2193    }   2315    class SupplicantStartingState extends State { 2316        @Override 2317        public void enter() { 2318            if (DBG) log(getName() + "\n"); 2319            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2320        } 2321        @Override 2322        public boolean processMessage(Message message) { 2323            if (DBG) log(getName() + message.toString() + "\n"); 2324            switch(message.what) { 2325                case WifiMonitor.SUP_CONNECTION_EVENT: 2326                    if (DBG) log("Supplicant connection established"); 2327                    WifiNative.setP2pDisable(1); 2328                    setWifiState(WIFI_STATE_ENABLED); 2329                    mSupplicantRestartCount = 0; 2330                    /* Reset the supplicant state to indicate the supplicant 2331                     * state is not known at this time */ 2332                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 2333                    mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); 2334                    /* Initialize data structures */ 2335                    mLastBssid = null; 2336                    mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 2337                    mLastSignalLevel = -1; 2338 2339                    mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand()); 2340 2341                    WifiConfigStore.initialize(mContext); 2342 2343                    sendSupplicantConnectionChangedBroadcast(true); 2344                    transitionTo(mDriverStartedState); 2345                    break; 2346                case WifiMonitor.SUP_DISCONNECTION_EVENT: 2347                    if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 2348                        loge("Failed to setup control channel, restart supplicant"); 2349                        WifiNative.killSupplicant(); 2350                        transitionTo(mDriverLoadedState); 2351                        sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 2352                    } else { 2353                        loge("Failed " + mSupplicantRestartCount + 2354                                " times to start supplicant, unload driver"); 2355                        mSupplicantRestartCount = 0; 2356                        transitionTo(mDriverLoadedState); 2357                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0)); 2358                    } 2359                    break; 2360                case CMD_LOAD_DRIVER: 2361                case CMD_UNLOAD_DRIVER: 2362                case CMD_START_SUPPLICANT: 2363                case CMD_STOP_SUPPLICANT: 2364                case CMD_START_AP: 2365                case CMD_STOP_AP: 2366                case CMD_START_DRIVER: 2367                case CMD_STOP_DRIVER: 2368                case CMD_SET_SCAN_MODE: 2369                case CMD_SET_SCAN_TYPE: 2370                case CMD_SET_HIGH_PERF_MODE: 2371                case CMD_SET_COUNTRY_CODE: 2372                case CMD_SET_FREQUENCY_BAND: 2373                case CMD_START_PACKET_FILTERING: 2374                case CMD_STOP_PACKET_FILTERING: 2375                    deferMessage(message); 2376                    break; 2377                default: 2378                    return NOT_HANDLED; 2379            } 2380            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2381            return HANDLED; 2382        } 2383    } 2384 2385    class SupplicantStartedState extends State { 2386        @Override 2387        public void enter() { 2388            if (DBG) log(getName() + "\n"); 2389            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2390            /* Initialize for connect mode operation at start */ 2391            mIsScanMode = false; 2392            /* Wifi is available as long as we have a connection to supplicant */ 2393            mNetworkInfo.setIsAvailable(true); 2394            /* Set scan interval */ 2395            long supplicantScanIntervalMs = Settings.Secure.getLong(mContext.getContentResolver(), 2396                    Settings.Secure.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, 2397                    mDefaultSupplicantScanIntervalMs); 2398            WifiNative.setScanIntervalCommand((int)supplicantScanIntervalMs / 1000); 2399        } 2400        @Override 2401        public boolean processMessage(Message message) { 2402            if (DBG) log(getName() + message.toString() + "\n"); 2403            WifiConfiguration config; 2404            boolean eventLoggingEnabled = true; 2405            switch(message.what) { 2406                case CMD_STOP_SUPPLICANT:   /* Supplicant stopped by user */ 2407                    transitionTo(mSupplicantStoppingState); 2408                    break; 2409                case WifiMonitor.SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */ 2410                    loge("Connection lost, restart supplicant"); 2411                    WifiNative.killSupplicant(); 2412                    WifiNative.closeSupplicantConnection(); 2413                    mNetworkInfo.setIsAvailable(false); 2414                    handleNetworkDisconnect(); 2415                    sendSupplicantConnectionChangedBroadcast(false); 2416                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 2417                    mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); 2418                    transitionTo(mDriverLoadedState); 2419                    sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 2420                    break; 2421                case WifiMonitor.SCAN_RESULTS_EVENT: 2422                    eventLoggingEnabled = false; 2423                    setScanResults(WifiNative.scanResultsCommand()); 2424                    sendScanResultsAvailableBroadcast(); 2425                    mScanResultIsPending = false; 2426                    break; 2427                case CMD_PING_SUPPLICANT: 2428                    boolean ok = WifiNative.pingCommand(); 2429                    mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 2430                    break; 2431                case CMD_ADD_OR_UPDATE_NETWORK: 2432                    config = (WifiConfiguration) message.obj; 2433                    mReplyChannel.replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, 2434                            WifiConfigStore.addOrUpdateNetwork(config)); 2435                    break; 2436                case CMD_REMOVE_NETWORK: 2437                    ok = WifiConfigStore.removeNetwork(message.arg1); 2438                    mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 2439                    break; 2440                case CMD_ENABLE_NETWORK: 2441                    ok = WifiConfigStore.enableNetwork(message.arg1, message.arg2 == 1); 2442                    mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 2443                    break; 2444                case CMD_ENABLE_ALL_NETWORKS: 2445                    long time =  android.os.SystemClock.elapsedRealtime(); 2446                    if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) { 2447                        WifiConfigStore.enableAllNetworks(); 2448                        mLastEnableAllNetworksTime = time; 2449                    } 2450                    break; 2451                case CMD_DISABLE_NETWORK: 2452                    ok = WifiConfigStore.disableNetwork(message.arg1, message.arg2); 2453                    mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 2454                    break; 2455                case CMD_BLACKLIST_NETWORK: 2456                    WifiNative.addToBlacklistCommand((String)message.obj); 2457                    break; 2458                case CMD_CLEAR_BLACKLIST: 2459                    WifiNative.clearBlacklistCommand(); 2460                    break; 2461                case CMD_SAVE_CONFIG: 2462                    ok = WifiConfigStore.saveConfig(); 2463                    mReplyChannel.replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 2464 2465                    // Inform the backup manager about a data change 2466                    IBackupManager ibm = IBackupManager.Stub.asInterface( 2467                            ServiceManager.getService(Context.BACKUP_SERVICE)); 2468                    if (ibm != null) { 2469                        try { 2470                            ibm.dataChanged("com.android.providers.settings"); 2471                        } catch (Exception e) { 2472                            // Try again later 2473                        } 2474                    } 2475                    break; 2476                    /* Cannot start soft AP while in client mode */ 2477                case CMD_START_AP: 2478                    loge("Failed to start soft AP with a running supplicant"); 2479                    setWifiApState(WIFI_AP_STATE_FAILED); 2480                    break; 2481                case CMD_SET_SCAN_MODE: 2482                    mIsScanMode = (message.arg1 == SCAN_ONLY_MODE); 2483                    break; 2484                case CMD_SAVE_NETWORK: 2485                    config = (WifiConfiguration) message.obj; 2486                    WifiConfigStore.saveNetwork(config); 2487                    break; 2488                case CMD_FORGET_NETWORK: 2489                    WifiConfigStore.forgetNetwork(message.arg1); 2490                    break; 2491                default: 2492                    return NOT_HANDLED; 2493            } 2494            if (eventLoggingEnabled) { 2495                EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2496            } 2497            return HANDLED; 2498        } 2499 2500        @Override 2501        public void exit() { 2502            mNetworkInfo.setIsAvailable(false); 2503        } 2504    }   233    private class AsyncServiceHandler extends Handler { 234 235        AsyncServiceHandler(android.os.Looper looper) { 236            super(looper); 237        } 238 239        @Override 240        public void handleMessage(Message msg) { 241            switch (msg.what) { 242                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 243                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 244                        Slog.d(TAG, "New client listening to asynchronous messages"); 245                        mClients.add((AsyncChannel) msg.obj); 246                    } else { 247                        Slog.e(TAG, "Client connection failure, error=" + msg.arg1); 248                    } 249                    break; 250                } 251                case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 252                    if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 253                        Slog.d(TAG, "Send failed, client connection lost"); 254                    } else { 255                        Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); 256                    } 257                    mClients.remove((AsyncChannel) msg.obj); 258                    break; 259                } 260                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { 261                    AsyncChannel ac = new AsyncChannel(); 262                    ac.connect(mContext, this, msg.replyTo); 263                    break; 264                } 265                case WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL: { 266                    mEnableTrafficStatsPoll = (msg.arg1 == 1); 267                    mTrafficStatsPollToken++; 268                    if (mEnableTrafficStatsPoll) { 269                        notifyOnDataActivity(); 270                        sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL, 271                                mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS); 272                    } 273                    break; 274                } 275                case WifiManager.CMD_TRAFFIC_STATS_POLL: { 276                    if (msg.arg1 == mTrafficStatsPollToken) { 277                        notifyOnDataActivity(); 278                        sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL, 279                                mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS); 280                    } 281                    break; 282                } 283                case WifiManager.CMD_CONNECT_NETWORK: { 284                    if (msg.obj != null) { 285                        mWifiStateMachine.connectNetwork((WifiConfiguration)msg.obj); 286                    } else { 287                        mWifiStateMachine.connectNetwork(msg.arg1); 288                    } 289                    break; 290                } 291                case WifiManager.CMD_SAVE_NETWORK: { 292                    mWifiStateMachine.saveNetwork((WifiConfiguration)msg.obj); 293                    break; 294                } 295                case WifiManager.CMD_FORGET_NETWORK: { 296                    mWifiStateMachine.forgetNetwork(msg.arg1); 297                    break; 298                } 299                case WifiManager.CMD_START_WPS: { 300                    //replyTo has the original source 301                    mWifiStateMachine.startWps(msg.replyTo, (WpsInfo)msg.obj); 302                    break; 303                } 304                case WifiManager.CMD_DISABLE_NETWORK: { 305                    mWifiStateMachine.disableNetwork(msg.replyTo, msg.arg1, msg.arg2); 306                    break; 307                } 308                default: { 309                    Slog.d(TAG, "WifiServicehandler.handleMessage ignoring msg=" + msg); 310                    break; 311                } 312            } 313        } 314    }   調用WifiStateMachine的connectNetwork方法。 935    public void connectNetwork(int netId) { 936        sendMessage(obtainMessage(CMD_CONNECT_NETWORK, netId, 0)); 937    } 938 939    public 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         */ 944        sendMessage(obtainMessage(CMD_CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, 945                0, wifiConfig)); 946    } 在ConnectedState時,新選擇network,連接,並且在收到連接好前轉到disconnectState 2969                case CMD_CONNECT_NETWORK: 2970                    int netId = message.arg1; 2971                    WifiConfiguration 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                     */ 2980                    if (config != null) { 2981                        netId = WifiConfigStore.selectNetwork(config); 2982                    } else { 2983                        WifiConfigStore.selectNetwork(netId); 2984                    } 2985 2986                    /* The state tracker handles enabling networks upon completion/failure */ 2987                    mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK); 2988 2989                    WifiNative.reconnectCommand(); 2990                    mLastExplicitNetworkId = netId; 2991                    mLastNetworkChoiceTime  = SystemClock.elapsedRealtime(); 2992                    mNextWifiActionExplicit = true; 2993                    if (DBG) log("Setting wifi connect explicit for netid " + netId); 2994                    /* Expect a disconnection from the old connection */ 2995                    transitionTo(mDisconnectingState); 2996                    break; SupplicantStateTracker.java收到CMD_CONNECT_NETWORK消息後追蹤狀態。主要是在reconnectCommand中做的連接。 152 153    class DefaultState extends State { 154        @Override 155         public void enter() { 156             if (DBG) Log.d(TAG, getName() + "\n"); 157         } 158        @Override 159        public boolean processMessage(Message message) { 160            if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 161            switch (message.what) { 162                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 163                    mAuthenticationFailuresCount++; 164                    mAuthFailureInSupplicantBroadcast = true; 165                    break; 166                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 167                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 168                    SupplicantState state = stateChangeResult.state; 169                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast); 170                    mAuthFailureInSupplicantBroadcast = false; 171                    transitionOnSupplicantStateChange(stateChangeResult); 172                    break; 173                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE: 174                    transitionTo(mUninitializedState); 175                    break; 176                case WifiStateMachine.CMD_CONNECT_NETWORK: 177                    mNetworksDisabledDuringConnect = true; 178                    break; 179                default: 180                    Log.e(TAG, "Ignoring " + message); 181                    break; 182            } 183            return HANDLED; 184        } 185    }   WifiNative.java 104    public 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{ 122    return (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{ 877    return 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) { 3287                       if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 3288                                       reply_len = -1; 3289                       else if (wpa_s->disconnected) { 3290                                       wpa_s->disconnected = 0; 3291                                       wpa_s->reassociate = 1; 3292                                       wpa_supplicant_req_scan(wpa_s, 0, 0); 3293                       } 3521       } else if (os_strcmp(buf, "SCAN") == 0) { 3522                       if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 3523                                       reply_len = -1; 3524                       else { 3525                                       if (!wpa_s->scanning && 3526                                           ((wpa_s->wpa_state <= WPA_SCANNING) || 3527                                            (wpa_s->wpa_state == WPA_COMPLETED))) { 3528                                                       wpa_s->scan_req = 2; 3529                                                       wpa_supplicant_req_scan(wpa_s, 0, 0); 3530                                       } else { 3531                                                       wpa_printf(MSG_DEBUG, "Ongoing scan action - " 3532                                                                          "reject new request"); 3533                                                       reply_len = os_snprintf(reply, reply_size, 3534                                                                                                       "FAIL-BUSY\n"); 3535                                       } 3536                       } 3537       } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 3538                       reply_len = wpa_supplicant_ctrl_iface_scan_results( 3539                                       wpa_s, reply, reply_size); 3540       } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 3541                       if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 3542                                       reply_len = -1; 3543       } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 3544                       if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 3545                                       reply_len = -1; 3546       } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 3547                       if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 3548                                       reply_len = -1; 3549       } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 3550                       reply_len = wpa_supplicant_ctrl_iface_add_network( 3551                                       wpa_s, reply, reply_size); 3552       } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 3553                       if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 3554                                       reply_len = -1; 3555       } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 3556                       if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 3557                                       reply_len = -1; 3558       } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 3559                       reply_len = wpa_supplicant_ctrl_iface_get_network( 3560                                       wpa_s, buf + 12, reply, reply_size); 3561#ifndef CONFIG_NO_CONFIG_WRITE 3562       } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 3563                       if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 3564                                       reply_len = -1; 3565#endif /* CONFIG_NO_CONFIG_WRITE */ 3566       } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 3567                       reply_len = wpa_supplicant_ctrl_iface_get_capability( 3568                                       wpa_s, buf + 15, reply, reply_size); 3569       } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 3570                       if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 3571                                       reply_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 log        0: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 wifi       0: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); 2155       case EVENT_SCAN_RESULTS: 2156                       wpa_supplicant_event_scan_results(wpa_s, data); 2157                       break; 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{ 34           struct wpa_ssid *ssid; 35           union wpa_event_data data; 36 37           ssid = wpa_supplicant_get_ssid(wpa_s); 38           if (ssid == NULL) 39                           return; 40 41           if (wpa_s->current_ssid == NULL) { 42                           wpa_s->current_ssid = ssid; 43                           if (wpa_s->current_ssid != NULL) 44                                           wpas_notify_network_changed(wpa_s); 45           } 46           wpa_supplicant_initiate_eapol(wpa_s); 47           wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured " 48                           "network - generating associated event"); 49           os_memset(&data, 0, sizeof(data)); 50           wpa_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, 4710                                                          struct wpa_driver_associate_params *params) 4711{ 4712       struct nl_msg *msg; 4713       int ret = -1; 4714       int count = 0; 4715 4716       wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); 4717 4718       if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) { 4719                       wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " 4720                                          "IBSS mode"); 4721                       return -1; 4722       } 4723 4724retry: 4725       msg = nlmsg_alloc(); 4726       if (!msg) 4727                       return -1; 4728 4729       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 4730                          NL80211_CMD_JOIN_IBSS, 0); 4731       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 4732 4733       if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid)) 4734                       goto nla_put_failure; 4735 4736       wpa_hexdump_ascii(MSG_DEBUG, "  * SSID", 4737                                         params->ssid, params->ssid_len); 4738       NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, 4739                       params->ssid); 4740       os_memcpy(drv->ssid, params->ssid, params->ssid_len); 4741       drv->ssid_len = params->ssid_len; 4742 4743       wpa_printf(MSG_DEBUG, "  * freq=%d", params->freq); 4744       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); 4745 4746       ret = nl80211_set_conn_keys(params, msg); 4747       if (ret) 4748                       goto nla_put_failure; 4749 4750       if (params->wpa_ie) { 4751                       wpa_hexdump(MSG_DEBUG, 4752                                           "  * Extra IEs for Beacon/Probe Response frames", 4753                                           params->wpa_ie, params->wpa_ie_len); 4754                       NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len, 4755                                       params->wpa_ie); 4756       } 4757 4758       ret = send_and_recv_msgs(drv, msg, NULL, NULL); 4759       msg = NULL; 4760       if (ret) { 4761                       wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)", 4762                                          ret, strerror(-ret)); 4763                       count++; 4764                       if (ret == -EALREADY && count == 1) { 4765                                       wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after " 4766                                                          "forced leave"); 4767                                       nl80211_leave_ibss(drv); 4768                                       nlmsg_free(msg); 4769                                       goto retry; 4770                       } 4771 4772                       goto nla_put_failure; 4773       } 4774       ret = 0; 4775       wpa_printf(MSG_DEBUG, "nl80211: Join IBSS request sent successfully"); 4776 4777nla_put_failure: 4778       nlmsg_free(msg); 4779       return ret; 4780} 首先看設置網卡工作模式 INFRA還是ADHOC 5148static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv, 5149                                           int ifindex, int mode) 5150{ 5151       struct nl_msg *msg; 5152       int ret = -ENOBUFS; 5153 5154       msg = nlmsg_alloc(); 5155       if (!msg) 5156                       return -ENOMEM; 5157 5158       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 5159                           0,NL80211_CMD_SET_INTERFACE, 0); 5160       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); 5161       NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode); 5162 5163       ret = send_and_recv_msgs(drv, msg, NULL, NULL); 5164       if (!ret) 5165                       return 0; 5166nla_put_failure: 5167       wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:" 5168                          " %d (%s)", ifindex, mode, ret, strerror(-ret)); 5169       return ret; 5170} NL80211_CMD_SET_INTERFACE command to kernel space driver => static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) => 1586       if (change) 1587                       err =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{ 4332       struct cfg80211_registered_device *rdev = info->user_ptr[0]; 4333       struct net_device *dev = info->user_ptr[1]; 4334       struct cfg80211_ibss_params ibss; 4335       struct wiphy *wiphy; 4336       struct cfg80211_cached_keys *connkeys = NULL; 4337       int err; 4338 4339       memset(&ibss, 0, sizeof(ibss)); 4340 4341       if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 4342                       return -EINVAL; 4343 4344       if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || 4345           !info->attrs[NL80211_ATTR_SSID] || 4346           !nla_len(info->attrs[NL80211_ATTR_SSID])) 4347                       return -EINVAL; 4348 4349       ibss.beacon_interval = 100; 4350 4351       if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { 4352                       ibss.beacon_interval = 4353                                       nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); 4354                       if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000) 4355                                       return -EINVAL; 4356       } 4357 4358       if (!rdev->ops->join_ibss) 4359                       return -EOPNOTSUPP; 4360 4361      if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) 4362                      return -EOPNOTSUPP;   //這個東西並不影響IBSS邏輯 4363 4364       wiphy = &rdev->wiphy; 4365 4366       if (info->attrs[NL80211_ATTR_MAC]) 4367                       ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); 4368       ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); 4369       ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); 4370 4371       if (info->attrs[NL80211_ATTR_IE]) { 4372                       ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]); 4373                       ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 4374       } 4375 4376       ibss.channel = ieee80211_get_channel(wiphy, 4377                       nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 4378       if (!ibss.channel || 4379           ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || 4380           ibss.channel->flags & IEEE80211_CHAN_DISABLED) 4381                       return -EINVAL; 4382 4383       ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 4384       ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; 4385 4386       if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { 4387                       u8 *rates = 4388                                       nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 4389                       int n_rates = 4390                                       nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 4391                       struct ieee80211_supported_band *sband = 4392                                       wiphy->bands[ibss.channel->band]; 4393                       int err; 4394                       err = ieee80211_get_ratemask(sband, rates, n_rates, 4395                                                                            &ibss.basic_rates); 4396                       if (err) 4397                                       return err; 4398       } 4399 4400       if (info->attrs[NL80211_ATTR_MCAST_RATE] && 4401           !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate, 4402                                       nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]))) 4403                       return -EINVAL; 4404 4405       if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) { 4406                       connkeys = nl80211_parse_connkeys(rdev, 4407                                                                       info->attrs[NL80211_ATTR_KEYS]); 4408                       if (IS_ERR(connkeys)) 4409                                       return PTR_ERR(connkeys); 4410       } 4411 4412       err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); 4413       if (err) 4414                       kfree(connkeys); 4415       return err; 4416}   In wl_cfg80211.c 1758static s32 1759wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, 1760       struct cfg80211_ibss_params *params) 1761{ 1762       struct wl_priv *wl = wiphy_priv(wiphy); 1763       struct cfg80211_bss *bss; 1764       struct ieee80211_channel *chan; 1765       struct wl_join_params join_params; 1766       struct cfg80211_ssid ssid; 1767       s32 scan_retry = 0; 1768       s32 err = 0; 1769       bool rollback_lock = false; 1770 1771       WL_TRACE(("In\n")); 1772       CHECK_SYS_UP(wl); 1773      if (params->bssid) {                         // remove the ibss-blocking code 1774                      WL_ERR(("Invalid bssid\n")); 1775                      return -EOPNOTSUPP;   1776       } 1777       bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len); 1778       if (!bss) { 1779                       memcpy(ssid.ssid, params->ssid, params->ssid_len); 1780                       ssid.ssid_len = params->ssid_len; 1781                       do { 1782                                       if (unlikely 1783                                                       (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) == 1784                                                       -EBUSY)) { 1785                                                       wl_delay(150); 1786                                       } else { 1787                                                       break; 1788                                       } 1789                       } while (++scan_retry < WL_SCAN_RETRY_MAX); 1790                       /* to allow scan_inform to propagate to cfg80211 plane */ 1791                       if (rtnl_is_locked()) { 1792                                       rtnl_unlock(); 1793                                       rollback_lock = true; 1794                       } 1795 1796                       /* wait 4 secons till scan done.... */ 1797                       schedule_timeout_interruptible(4 * HZ); 1798                       if (rollback_lock) 1799                                       rtnl_lock(); 1800                       bss = cfg80211_get_ibss(wiphy, NULL, 1801                                       params->ssid, params->ssid_len); 1802       } 1803       if (bss) { 1804                       wl->ibss_starter = false; 1805                       WL_DBG(("Found IBSS\n")); 1806       } else { 1807                       wl->ibss_starter = true; 1808       } 1809       chan = params->channel; 1810       if (chan) 1811                       wl->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       */ 1816       memset(&join_params, 0, sizeof(join_params)); 1817       memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, 1818                       params->ssid_len); 1819       join_params.ssid.SSID_len = htod32(params->ssid_len); 1820       if (params->bssid) 1821                       memcpy(&join_params.params.bssid, params->bssid, 1822                                       ETHER_ADDR_LEN); 1823       else 1824                       memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); 1825 1826       err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, 1827                       sizeof(join_params), false); 1828       if (unlikely(err)) { 1829                       WL_ERR(("Error (%d)\n", err)); 1830                       return err; 1831       } 1832       return 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{ 5257       memset(wl->evt_handler, 0, sizeof(wl->evt_handler)); 5258 5259       wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status; 5260       wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status; 5261       wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status; 5262       wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status; 5263       wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status; 5264       wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status; 5265       wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status; 5266       wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status; 5267       wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status; 5268       wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status; 5269       wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame; 5270       wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame; 5271       wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame; 5272       wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; 5273       wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; 5274       wl->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) 8    BOARD_USES_QCOM_HARDWARE := true 9    DYNAMIC_SHARED_LIBV8SO := true 10    BOARD_USES_ADRENO_200 := true 11    HAVE_ADRENO200_SOURCE := true 12    HAVE_ADRENO200_SC_SOURCE := true 13    HAVE_ADRENO200_FIRMWARE := true 14    BOARD_USES_QCNE := true 15    USE_OPENGL_RENDERER := true 16    BOARD_USE_QCOM_LLVM_CLANG_RS := true 17    ifneq ($(BUILD_TINY_ANDROID), true) 18    BOARD_VENDOR_QCOM_GPS_LOC_API_AMSS_VERSION := 50001 19    BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE := default 20    BOARD_CAMERA_LIBRARIES := libcamera 21    BOARD_HAVE_BLUETOOTH := true 22    BOARD_HAVE_BLUETOOTH_BCM := true 23    BOARD_HAVE_QCOM_FM := false 24    #BOARD_USES_GENERIC_AUDIO := true 25    HOSTAPD_VERSION := VER_2_0_DEV_BCM 26    BOARD_HOSTAPD_DRIVER := NL80211 27    #BOARD_HAS_QCOM_WLAN := true 28    BOARD_WPA_SUPPLICANT_DRIVER := NL80211 29    WPA_SUPPLICANT_VERSION := VER_0_8_X_BCM 30 31    #WIFI_DRIVER_MODULE_PATH := "/system/etc/bcm4330/dhd.ko" 32    WIFI_DRIVER_MODULE_NAME := "dhd" 33    WIFI_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" 34    BOARD_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  := "" 40    WIFI_DRIVER_FW_PATH_PARAM := "/sys/module/bcmdhd/parameters/firmware_path" 41    WIFI_DRIVER_FW_PATH_STA := "/system/etc/bcm4330/sdio_g_pool_pno_pktfilter_keepalive_wapi_wme_idsup_idauth_sta_aoe.bin" 42    WIFI_DRIVER_FW_PATH_AP  := "/system/etc/bcm4330/sdio_g_pool_pno_pktfilter_keepalive_wapi_wme_idsup_idauth_apsta_aoe.bin" 43    WIFI_DRIVER_FW_PATH_P2P := "/system/etc/bcm4330/sdio_g_pool_pno_pktfilter_keepalive_wapi_wme_idsup_idauth_p2p_aoe.bin" 44    BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_bcmdhd 45    BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_bcmdhd 46    BOARD_WLAN_DEVICE := bcmdhd 47    endif   # !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
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved