Patch android wifi to enable IBSS/WEP support

来源:互联网 发布:mac连接wifi经常断线 编辑:程序博客网 时间:2024/05/29 13:00

Only To developers.

wpa_supplicant 0.8.x, wpa_supplicant_drvier nl80211, wifi chip bcm4330.

转载请注明出处:http://blog.csdn.net/zirconsdu/article/details/8571260 

最后修改版,能连接使用ADHOC,能显示信号强度;

Patch

  1. 修改Settings/wifi中的代码以显示[IBSS][WEP] ssid或没有名字的ssid.

UI显示SSID列表时,会获取从wpa_supplicant最近扫描到的APswpa_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;

               }

  1. 修改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;

                                }

wpa_supplicant在扫描结果中找不到匹配的AP进行连接时,会用wpa_supplicant_pick_new_network选择IBSS ssid进行关联,增加代码跳过IBSS AP,因为此时该AP肯定不在扫描结果中。否则会导致去连接这个AP,导致后续扫描出错。

_wpa_supplicant_event_scan_results(…) @ events.c

                } else {

                                wpa_scan_results_free(scan_res);

                                wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found");

                                ssid = wpa_supplicant_pick_new_network(wpa_s);

                                if (ssid) {

                                               if(ssid->mode == IEEE80211_MODE_IBSS) {

                                                               wpa_dbg(wpa_s, MSG_DEBUG, "ibss mode ssid selected by pcik_new_ssid is skipped");

                                                               return -1;

                                               }

                                                wpa_dbg(wpa_s, MSG_DEBUG, "Setup a new network");

                                                wpa_supplicant_associate(wpa_s, NULL, ssid);

                                                wpa_supplicant_rsn_preauth_scan_results(wpa_s);

                                } else {

  1. linux内核nl80211驱动和bcm4330驱动

wpa_driver_nl80211_ibss发送NL80211_CMD_SET_INTERFACE NL80211_CMD_JOIN_IBSSlinux 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时,设置固件auth模式为OPEN_SYSTEM rather than SHARED_KEY, 设置Beacon Intervalstarter freq,然后连接AP。修改代码如下,

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;

                s32 err = 0;

 

                //WL_TRACE(("In\n"));

                printk("In wl_cfg80211_join_ibss\n");

                CHECK_SYS_UP(wl);

               if (params->bssid) {    // 此处注释掉以下两行;否则需要在wpa_supplicant wpa_driver_nl80211_join_ibss中修改在IBSS模式下传入的param->bssid为NULL.

//                           WL_ERR(("Invalid bssid\n"));

                               printk("wl_cfg80211_join_ibss: with bssid, 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;

                }

 

                /*

                 * 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);

                join_params_size = sizeof(join_params.ssid);

                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);

                }

                wl_update_prof(wl, dev, NULL, &join_params.params.bssid, WL_PROF_BSSID);

 

                chan = params->channel;

                if (chan) {

                                u32 target_channel;

 

                                wl->channel = ieee80211_frequency_to_channel(chan->center_freq);

                                if (params->channel_fixed) {

                                                printk("wl_cfg80211_join_ibss: set channel %d in join params[len=%d]\n", wl->channel, join_params_size);

                                                /* adding chanspec */

                                                wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);

                                                printk("wl_cfg80211_join_ibss: channel %d setted in join params[len=%d]\n", wl->channel, 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;

                }

 

                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:

                return err;

}

修改__wl_cfg80211_scan以设置BCM4330IBSS模式下也能正常扫描出结果。

In __wl_cfg80211_scan(…) @ wl_cfg80211.c

add escan_req = false initialization.

after

                iscan_req = false;

modify  Legacy scanif (!wl->p2p_supported || !p2p_scan(wl))

to

                if ((!wl->p2p_supported || !p2p_scan(wl)) && !wl_is_ibssmode(wl, ndev))

modify else if(escan_req)块中if (wl->p2p_supported)

to

if (wl->p2p_supported && !wl_is_ibssmode(wl, ndev))

modify direct scansr->ssid.SSID_len =

                                                                min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);

to

                                if(ssids)

                                                sr->ssid.SSID_len =

                                                                min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);

                                else

                                                sr->ssid.SSID_len = 0;

增加函数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;

}

增加两个函数wl_update_ibss_infowl_ibss_joined_done

static s32 wl_update_ibss_info(struct wl_priv *wl, struct net_device *ndev)

{

                struct cfg80211_bss *bss;

                struct wl_bss_info *bi;

                struct wlc_ssid *ssid;

                struct bcm_tlv *tim;

                s32 beacon_interval;

                s32 dtim_period;

                size_t ie_len;

                u8 *ie;

                u8 *curbssid;

                s32 err = 0;

                struct wiphy *wiphy;

 

                wiphy = wl_to_wiphy(wl);

 

                if (!wl_is_ibssmode(wl, ndev))

                                return err;

 

                ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID);

                curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);

                bss = cfg80211_get_bss(wiphy, NULL, curbssid,

                                ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_IBSS,

                                WLAN_CAPABILITY_IBSS);

 

                mutex_lock(&wl->usr_sync);

                if (!bss) {

                                WL_DBG(("Could not find the AP\n"));

                                *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);

                                err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,

                                                wl->extra_buf, WL_EXTRA_BUF_MAX, false);

                                if (unlikely(err)) {

                                                WL_ERR(("Could not get bss info %d\n", err));

                                                goto update_ibss_info_out;

                                }

                                bi = (struct wl_bss_info *)(wl->extra_buf + 4);

                                if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {

                                                WL_ERR(("BSSID and curbssid mismatch\n"));

                                                err = -EIO;

                                                goto update_ibss_info_out;

                                }

                                err = wl_inform_single_bss(wl, bi);

                                if (unlikely(err))

                                                goto update_ibss_info_out;

 

                                ie = ((u8 *)bi) + bi->ie_offset;

                                ie_len = bi->ie_length;

                                beacon_interval = cpu_to_le16(bi->beacon_period);

                } else {

                                WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));

                                ie = bss->information_elements;

                                ie_len = bss->len_information_elements;

                                beacon_interval = bss->beacon_interval;

                                cfg80211_put_bss(bss);

                }

 

                tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);

                if (tim) {

                                dtim_period = tim->data[1];

                } else {

                                /*

                                * active scan was done so we could not get dtim

                                * information out of probe response.

                                * so we speficially query dtim information.

                                */

                                err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,

                                                &dtim_period, sizeof(dtim_period), false);

                                if (unlikely(err)) {

                                                WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));

                                                goto update_ibss_info_out;

                                }

                }

 

                wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);

                wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);

 

update_ibss_info_out:

                mutex_unlock(&wl->usr_sync);

                return err;

}

 

static s32

wl_ibss_joined_done(struct wl_priv *wl, struct net_device *ndev,

                const wl_event_msg_t *e, void *data)

{

                s32 err = 0;

 

                WL_DBG(("%s enter\n", __FUNCTION__));

                if (wl->scan_request) {

                                printk("Cancel ongoing scan in %s\n", __FUNCTION__);

                                wl_cfg80211_scan_abort(wl, ndev);

                }

 

                wl_get_assoc_ies(wl, ndev);

                wl_update_ibss_info(wl, ndev);

                wl_update_pmklist(ndev, wl->pmk_list, err);

                cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);

 

                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 (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);// =>EVENT_ASSOC

                                                                WL_DBG(("joined in IBSS network\n"));

                                                } else {

                                                …………………………….

                                                }

                                                if (wl_get_drv_status(wl, CONNECTING, ndev)) {

                                                                wl_bss_connect_done(wl, ndev, e, data, false);

                                                }

                                } else {

                                                printk("%s nothing\n", __FUNCTION__);

                                }

                }

或者第二种:

                } else {

                                WL_DBG(("wl_notify_connect_status : event %d status : %d \n",

                                ntoh32(e->event_type), ntoh32(e->status)));

 

                                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)) {

                                                                char * addr_ptr = (char *)&e->addr;

                                                                printk("linkup in ibss mode, before to call cfg80211_ibss_joined\n");     

                                                                wl_ibss_joined_done(wl, ndev, e, data);

                                                                wl_clr_drv_status(wl, CONNECTING, ndev); // IBSS模式下,CONNECTING和CONNECTED两个标志可以酌情不使用

                                                                wl_set_drv_status(wl, CONNECTED, ndev);

                                                                WL_DBG(("joined in IBSS network\n"));

                                                } else {

                                                …………………………….

                                                }

                                                if (wl_get_drv_status(wl, CONNECTING, ndev)) {

                                                                wl_bss_connect_done(wl, ndev, e, data, false);

                                                }

                                } else {

                                                printk("%s nothing\n", __FUNCTION__);

                                }

                }

wl_cfg80211_get_station中增加IBSS模式下的得到RSSI Signal的代码,显示信号强度。

                CHECK_SYS_UP(wl);

                if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {

                                ……

                } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) {

                                ……

                } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_IBSS) {

                                                u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);

                                                printk("%s is called for IBSS mode!!!!!!!\n", __FUNCTION__);

                                                if (!wl_get_drv_status(wl, CONNECTED, dev) ||    // IBSS模式下不使用CONNECTED标志时,可以不要此条件

                                                    (dhd_is_associated(dhd, NULL) == FALSE)) {

                                                                WL_ERR(("NOT assoc\n"));

                                                                err = -ENODEV;

                                                                goto get_station_err_ibss;

                                                }

                                                if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {

                                                                WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n",

                                                                                MAC2STR(mac), MAC2STR(curmacp)));

                                                }

 

                                                /* Report the current tx rate */

                                                err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);

                                                if (err) {

                                                                WL_ERR(("Could not get rate (%d)\n", err));

                                                } else {

                                                                rate = dtoh32(rate);

                                                                sinfo->filled |= STATION_INFO_TX_BITRATE;

                                                                sinfo->txrate.legacy = rate * 5;

                                                                WL_DBG(("Rate %d Mbps\n", (rate / 2)));

                                                }

 

                                                memset(&scb_val, 0, sizeof(scb_val));

                                                scb_val.val = 0;

                                                err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,

                                                                                sizeof(scb_val_t), false);

                                                if (err) {

                                                                WL_ERR(("Could not get rssi (%d)\n", err));

                                                                goto get_station_err_ibss;

                                                }

 

                                                rssi = dtoh32(scb_val.val);

                                                sinfo->filled |= STATION_INFO_SIGNAL;

                                                sinfo->signal = rssi;

                                                WL_DBG(("RSSI %d dBm\n", rssi));

 

get_station_err_ibss:

                                if (err) {

                                                /* Disconnect due to zero BSSID or error to get RSSI */

                                                WL_ERR(("force cfg80211_disconnected\n"));

                                                wl_clr_drv_status(wl, CONNECTED, dev);  // IBSS模式下不使用CONNECTED标志时,可以酌情处理

                                                cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);

                                                wl_link_down(wl);

                                }

                }

 

                return err;

}

Patch END.

 

Principle and 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

WifiConfigControllerMVC中的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()

总之,发出SCANCONNECT的异步命令,等待事件通知做界面响应。主要就是不停的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>

 

 

  1. 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作为一个serviceWifiService.javaframeworks/base/services/java/com/android/server/目录下。但其实现使用的WifiStateMachineframeworks/base/wifi/java/android/net/wifi/目录下。

WifiStateMachine状态机使用WifiNative wpa_ctrlwpa_supplicant通讯, WifiMonitor监听WifiNative的异步消息。客户端传来的命令和WifiMonitor监听到的响应汇入WifiStateMachine的消息队列,驱动WifiStateMachine转动起来。

WifiStateMachine的方法中同步的带有’sync’字样,异步的是直接发送消息,通过WifiMonitor异步收集结果,WifiMonitor就是个ReceiverThread加消息协议转换。WifiMonitor在使用unix domain socket ctrl interface时是pollsocket上,有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.javaP2p的各状态下对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    }

 

调用WifiStateMachineconnectNetwork方法。

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上,该socketrecv函数是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.rcwpa_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_supplicantlogger输出时,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_resultspick 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模式时没有执行,需要patchWLC_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_ifmodewl_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固件,err0,表发送成功;

WLC_SET_SSID的结果以异步形式由固件发送回来。此时收到的WLC_E_SET_SSIDstatusWLC_E_STATUS_NO_NETWORKS

设置WLC_SET_INFRA后,修改join_ibss相关代码,可以收到WLC_E_SET_SSID with status WLC_E_STATUS_SUCCESSFUL,连接上IBSS

 

驱动中在IBSS时收到的主要是WLC_E_LINKWLC_E_JOINWLC_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;

 

driver_nl80211中,event上行路线。

netlink_receive处理link时间,调用wpa_driver_nl80211_event_rtm_newlink/dellink,调用wpa_driver_nl80211_event_link处理link层面事件,调用wpa_supplicant_event通知wpa_s

mac layer me处理层面,mlme_event调用mlme_event_mgmt处理management帧事件,其余如datacontrol帧使用mlme_event_xxxx系列函数处理,然后调用wpa_supplicant_event通知wpa_s

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}

 

scan results内核数据更新

wl_escan_handler中对扫描到的每个报告帧解析,添加到内核网卡数据结构bss_list中;

wl_escan_handler => wl_inform_bss => wl_inform_single_bss

连接成功AP后,也会更新该数据结构。

wl_bss_connect_done => wl_update_bss_info(not ibss) => wl_inform_single_bss

以后wl_inform_single_bss => cfg80211_inform_bss_frame => cfg80211_bss_update操作rb tree.

还有一条线                                              cfg80211_inform_bss => cfg80211_bss_update此条线能找到

wl_ibss_join_done => wl_update_ibss_info(ibss) => wl_inform_single_bss

 

dhd_rx_frame =>

dhd_wl_host_event =>

 wl_host_event + wl_iw_event + wl_cfg80211_event

 

以下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