(一百五十一)Android P 真正创建sta iface的地方
1.流程回顾
之前在(一百四十八)Android P wifi启动过程中的sta interface创建 中梳理了sta interface的创建流程,在(一百四十九)Android P WificondControl的setupInterfaceForClientMode梳理了wificond的setup interface,在(一百五十)Android P SupplicantStaIfaceHal的setupIface SupplicantStaIfaceHal的setupIface
但都没有找到sta iface真正创建的地方,又回头梳理了一遍终于找到了。
真正创建的地方还是(一百五十)Android P SupplicantStaIfaceHal的setupIface SupplicantStaIfaceHal的setupIface
后续分析补充,下面分析的不对
2.流程梳理
2.1 supplicant.cpp
wpa_supplicant_add_iface
std::pair<SupplicantStatus, sp<ISupplicantIface>>
Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
{android::sp<ISupplicantIface> iface;// Check if required |ifname| argument is empty.if (iface_info.name.empty()) {return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};}// Try to get the wpa_supplicant record for this iface, return// the iface object with the appropriate status code if it exists.SupplicantStatus status;std::tie(status, iface) = getInterfaceInternal(iface_info);if (status.code == SupplicantStatusCode::SUCCESS) {return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},iface};}struct wpa_interface iface_params = {};iface_params.driver = kIfaceDriverName;if (iface_info.type == IfaceType::P2P) {if (ensureConfigFileExists(kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {wpa_printf(MSG_ERROR, "Conf file does not exists: %s",kP2pIfaceConfPath);return {{SupplicantStatusCode::FAILURE_UNKNOWN,"Conf file does not exist"},{}};}iface_params.confname = kP2pIfaceConfPath;int ret = access(kP2pIfaceConfOverlayPath, R_OK);if (ret == 0) {iface_params.confanother = kP2pIfaceConfOverlayPath;}} else {if (ensureConfigFileExists(kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {wpa_printf(MSG_ERROR, "Conf file does not exists: %s",kStaIfaceConfPath);return {{SupplicantStatusCode::FAILURE_UNKNOWN,"Conf file does not exist"},{}};}iface_params.confname = kStaIfaceConfPath;int ret = access(kStaIfaceConfOverlayPath, R_OK);if (ret == 0) {iface_params.confanother = kStaIfaceConfOverlayPath;}}iface_params.ifname = iface_info.name.c_str();struct wpa_supplicant* wpa_s =wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);if (!wpa_s) {return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};}// The supplicant core creates a corresponding hidl object via// HidlManager when |wpa_supplicant_add_iface| is called.return getInterfaceInternal(iface_info);
}
2.2 wpa_supplicant.c
/*** wpa_supplicant_add_iface - Add a new network interface* @global: Pointer to global data from wpa_supplicant_init()* @iface: Interface configuration options* @parent: Parent interface or %NULL to assign new interface as parent* Returns: Pointer to the created interface or %NULL on failure** This function is used to add new network interfaces for %wpa_supplicant.* This can be called before wpa_supplicant_run() to add interfaces before the* main event loop has been started. In addition, new interfaces can be added* dynamically while %wpa_supplicant is already running. This could happen,* e.g., when a hotplug network adapter is inserted.*/
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,struct wpa_interface *iface,struct wpa_supplicant *parent)
{struct wpa_supplicant *wpa_s;struct wpa_interface t_iface;struct wpa_ssid *ssid;if (global == NULL || iface == NULL)return NULL;wpa_s = wpa_supplicant_alloc(parent);if (wpa_s == NULL)return NULL;wpa_s->global = global;t_iface = *iface;if (global->params.override_driver) {wpa_printf(MSG_DEBUG, "Override interface parameter: driver ""('%s' -> '%s')",iface->driver, global->params.override_driver);t_iface.driver = global->params.override_driver;}if (global->params.override_ctrl_interface) {wpa_printf(MSG_DEBUG, "Override interface parameter: ""ctrl_interface ('%s' -> '%s')",iface->ctrl_interface,global->params.override_ctrl_interface);t_iface.ctrl_interface =global->params.override_ctrl_interface;}if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {wpa_printf(MSG_DEBUG, "Failed to add interface %s",iface->ifname);wpa_supplicant_deinit_iface(wpa_s, 0, 0);return NULL;}/* Notify the control interfaces about new iface */if (wpas_notify_iface_added(wpa_s)) {wpa_supplicant_deinit_iface(wpa_s, 1, 0);return NULL;}/* Notify the control interfaces about new networks for non p2p mgmt* ifaces. */if (iface->p2p_mgmt == 0) {for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)wpas_notify_network_added(wpa_s, ssid);}wpa_s->next = global->ifaces;global->ifaces = wpa_s;wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);#ifdef CONFIG_P2Pif (wpa_s->global->p2p == NULL &&!wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&wpas_p2p_add_p2pdev_interface(wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {wpa_printf(MSG_INFO,"P2P: Failed to enable P2P Device interface");/* Try to continue without. P2P will be disabled. */}
#endif /* CONFIG_P2P */return wpa_s;
}
看下初始化的逻辑
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,struct wpa_interface *iface)
{struct wpa_driver_capa capa;int capa_res;u8 dfs_domain;wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver ""'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,iface->confname ? iface->confname : "N/A",iface->driver ? iface->driver : "default",iface->ctrl_interface ? iface->ctrl_interface : "N/A",iface->bridge_ifname ? iface->bridge_ifname : "N/A");if (iface->confname) {
#ifdef CONFIG_BACKEND_FILEwpa_s->confname = os_rel2abs_path(iface->confname);if (wpa_s->confname == NULL) {wpa_printf(MSG_ERROR, "Failed to get absolute path ""for configuration file '%s'.",iface->confname);return -1;}wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",iface->confname, wpa_s->confname);
#else /* CONFIG_BACKEND_FILE */wpa_s->confname = os_strdup(iface->confname);
#endif /* CONFIG_BACKEND_FILE */wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);if (wpa_s->conf == NULL) {wpa_printf(MSG_ERROR, "Failed to read or parse ""configuration '%s'.", wpa_s->confname);return -1;}wpa_s->confanother = os_rel2abs_path(iface->confanother);wpa_config_read(wpa_s->confanother, wpa_s->conf);/** Override ctrl_interface and driver_param if set on command* line.*/if (iface->ctrl_interface) {os_free(wpa_s->conf->ctrl_interface);wpa_s->conf->ctrl_interface =os_strdup(iface->ctrl_interface);}if (iface->driver_param) {os_free(wpa_s->conf->driver_param);wpa_s->conf->driver_param =os_strdup(iface->driver_param);}if (iface->p2p_mgmt && !iface->ctrl_interface) {os_free(wpa_s->conf->ctrl_interface);wpa_s->conf->ctrl_interface = NULL;}} elsewpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,iface->driver_param);if (wpa_s->conf == NULL) {wpa_printf(MSG_ERROR, "\nNo configuration found.");return -1;}if (iface->ifname == NULL) {wpa_printf(MSG_ERROR, "\nInterface name is required.");return -1;}if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",iface->ifname);return -1;}os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));if (iface->bridge_ifname) {if (os_strlen(iface->bridge_ifname) >=sizeof(wpa_s->bridge_ifname)) {wpa_printf(MSG_ERROR, "\nToo long bridge interface ""name '%s'.", iface->bridge_ifname);return -1;}os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,sizeof(wpa_s->bridge_ifname));}/* RSNA Supplicant Key Management - INITIALIZE */eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);eapol_sm_notify_portValid(wpa_s->eapol, FALSE);/* Initialize driver interface and register driver event handler before* L2 receive handler so that association events are processed before* EAPOL-Key packets if both become available for the same select()* call. */if (wpas_init_driver(wpa_s, iface) < 0)return -1;if (wpa_supplicant_init_wpa(wpa_s) < 0)return -1;wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :NULL);wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,wpa_s->conf->dot11RSNAConfigPMKLifetime)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigPMKLifetime");return -1;}if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigPMKReauthThreshold");return -1;}if (wpa_s->conf->dot11RSNAConfigSATimeout &&wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,wpa_s->conf->dot11RSNAConfigSATimeout)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigSATimeout");return -1;}wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,&wpa_s->hw.num_modes,&wpa_s->hw.flags,&dfs_domain);if (wpa_s->hw.modes) {u16 i;for (i = 0; i < wpa_s->hw.num_modes; i++) {if (wpa_s->hw.modes[i].vht_capab) {wpa_s->hw_capab = CAPAB_VHT;break;}if (wpa_s->hw.modes[i].ht_capab &HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)wpa_s->hw_capab = CAPAB_HT40;else if (wpa_s->hw.modes[i].ht_capab &&wpa_s->hw_capab == CAPAB_NO_HT_VHT)wpa_s->hw_capab = CAPAB_HT;}}capa_res = wpa_drv_get_capa(wpa_s, &capa);if (capa_res == 0) {wpa_s->drv_capa_known = 1;wpa_s->drv_flags = capa.flags;wpa_s->drv_enc = capa.enc;wpa_s->drv_smps_modes = capa.smps_modes;wpa_s->drv_rrm_flags = capa.rrm_flags;wpa_s->probe_resp_offloads = capa.probe_resp_offloads;wpa_s->max_scan_ssids = capa.max_scan_ssids;wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;wpa_s->max_sched_scan_plan_interval =capa.max_sched_scan_plan_interval;wpa_s->max_sched_scan_plan_iterations =capa.max_sched_scan_plan_iterations;wpa_s->sched_scan_supported = capa.sched_scan_supported;wpa_s->max_match_sets = capa.max_match_sets;wpa_s->max_remain_on_chan = capa.max_remain_on_chan;wpa_s->max_stations = capa.max_stations;wpa_s->extended_capa = capa.extended_capa;wpa_s->extended_capa_mask = capa.extended_capa_mask;wpa_s->extended_capa_len = capa.extended_capa_len;wpa_s->num_multichan_concurrent =capa.num_multichan_concurrent;wpa_s->wmm_ac_supported = capa.wmm_ac_supported;if (capa.mac_addr_rand_scan_supported)wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;if (wpa_s->sched_scan_supported &&capa.mac_addr_rand_sched_scan_supported)wpa_s->mac_addr_rand_supported |=(MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);}if (wpa_s->max_remain_on_chan == 0)wpa_s->max_remain_on_chan = 1000;/** Only take p2p_mgmt parameters when P2P Device is supported.* Doing it here as it determines whether l2_packet_init() will be done* during wpa_supplicant_driver_init().*/if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)wpa_s->p2p_mgmt = iface->p2p_mgmt;elseiface->p2p_mgmt = 1;if (wpa_s->num_multichan_concurrent == 0)wpa_s->num_multichan_concurrent = 1;if (wpa_supplicant_driver_init(wpa_s) < 0)return -1;#ifdef CONFIG_TDLSif ((!iface->p2p_mgmt ||!(wpa_s->drv_flags &WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&wpa_tdls_init(wpa_s->wpa))return -1;
#endif /* CONFIG_TDLS */if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");return -1;}#ifdef CONFIG_FSTif (wpa_s->conf->fst_group_id) {struct fst_iface_cfg cfg;struct fst_wpa_obj iface_obj;fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,sizeof(cfg.group_id));cfg.priority = wpa_s->conf->fst_priority;cfg.llt = wpa_s->conf->fst_llt;wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,&iface_obj, &cfg);if (!wpa_s->fst) {wpa_msg(wpa_s, MSG_ERROR,"FST: Cannot attach iface %s to group %s",wpa_s->ifname, cfg.group_id);return -1;}}
#endif /* CONFIG_FST */if (wpas_wps_init(wpa_s))return -1;#ifdef CONFIG_GAS_SERVERwpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);if (!wpa_s->gas_server) {wpa_printf(MSG_ERROR, "Failed to initialize GAS server");return -1;}
#endif /* CONFIG_GAS_SERVER */#ifdef CONFIG_DPPif (wpas_dpp_init(wpa_s) < 0)return -1;
#endif /* CONFIG_DPP */if (wpa_supplicant_init_eapol(wpa_s) < 0)return -1;wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);if (wpa_s->ctrl_iface == NULL) {wpa_printf(MSG_ERROR,"Failed to initialize control interface '%s'.\n""You may have another wpa_supplicant process ""already running or the file was\n""left by an unclean termination of wpa_supplicant ""in which case you will need\n""to manually remove this file before starting ""wpa_supplicant again.\n",wpa_s->conf->ctrl_interface);return -1;}wpa_s->gas = gas_query_init(wpa_s);if (wpa_s->gas == NULL) {wpa_printf(MSG_ERROR, "Failed to initialize GAS query");return -1;}if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");return -1;}if (wpa_bss_init(wpa_s) < 0)return -1;#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
#ifdef CONFIG_MESHdl_list_init(&wpa_s->mesh_external_pmksa_cache);
#endif /* CONFIG_MESH */
#endif /* CONFIG_PMKSA_CACHE_EXTERNAL *//** Set Wake-on-WLAN triggers, if configured.* Note: We don't restore/remove the triggers on shutdown (it doesn't* have effect anyway when the interface is down).*/if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)return -1;#ifdef CONFIG_EAP_PROXY
{size_t len;wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,wpa_s->imsi, &len);if (wpa_s->mnc_len > 0) {wpa_s->imsi[len] = '\0';wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",wpa_s->imsi, wpa_s->mnc_len);} else {wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");}
}
#endif /* CONFIG_EAP_PROXY */if (pcsc_reader_init(wpa_s) < 0)return -1;if (wpas_init_ext_pw(wpa_s) < 0)return -1;wpas_rrm_reset(wpa_s);wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);#ifdef CONFIG_HS20hs20_init(wpa_s);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBOif (wpa_s->conf->oce) {if ((wpa_s->conf->oce & OCE_STA) &&(wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))wpa_s->enable_oce = OCE_STA;if ((wpa_s->conf->oce & OCE_STA_CFON) &&(wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {/* TODO: Need to add STA-CFON support */wpa_printf(MSG_ERROR,"OCE STA-CFON feature is not yet supported");}}wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
#endif /* CONFIG_MBO */wpa_supplicant_set_default_scan_ies(wpa_s);return 0;
}
看下这段逻辑
/* Initialize driver interface and register driver event handler before* L2 receive handler so that association events are processed before* EAPOL-Key packets if both become available for the same select()* call. */if (wpas_init_driver(wpa_s, iface) < 0)return -1;static int wpas_init_driver(struct wpa_supplicant *wpa_s,struct wpa_interface *iface)
{const char *ifname, *driver, *rn;driver = iface->driver;
next_driver:if (wpa_supplicant_set_driver(wpa_s, driver) < 0)return -1;wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);if (wpa_s->drv_priv == NULL) {const char *pos;pos = driver ? os_strchr(driver, ',') : NULL;if (pos) {wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize ""driver interface - try next driver wrapper");driver = pos + 1;goto next_driver;}wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver ""interface");return -1;}if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected ""driver_param '%s'", wpa_s->conf->driver_param);return -1;}ifname = wpa_drv_get_ifname(wpa_s);if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced ""interface name with '%s'", ifname);os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));}rn = wpa_driver_get_radio_name(wpa_s);if (rn && rn[0] == '\0')rn = NULL;wpa_s->radio = radio_add_interface(wpa_s, rn);if (wpa_s->radio == NULL)return -1;return 0;
}
2.3 driver.h
/* driver_ops */
static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,const char *ifname)
{if (wpa_s->driver->init2)return wpa_s->driver->init2(wpa_s, ifname,wpa_s->global_drv_priv);if (wpa_s->driver->init) {return wpa_s->driver->init(wpa_s, ifname);}return NULL;
}
搜了下有对init2的初始化./src/drivers/driver_nl80211.c:10360: .init2 = wpa_driver_nl80211_init
/*** wpa_driver_nl80211_init - Initialize nl80211 driver interface* @ctx: context to be used when calling wpa_supplicant functions,* e.g., wpa_supplicant_event()* @ifname: interface name, e.g., wlan0* @global_priv: private driver global data from global_init()* Returns: Pointer to private data, %NULL on failure*/
static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,void *global_priv)
{return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL,NULL);
}static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,void *global_priv, int hostapd,const u8 *set_addr,const char *driver_params)
{struct wpa_driver_nl80211_data *drv;struct i802_bss *bss;if (global_priv == NULL)return NULL;drv = os_zalloc(sizeof(*drv));if (drv == NULL)return NULL;drv->global = global_priv;drv->ctx = ctx;drv->hostapd = !!hostapd;drv->eapol_sock = -1;/** There is no driver capability flag for this, so assume it is* supported and disable this on first attempt to use if the driver* rejects the command due to missing support.*/drv->set_rekey_offload = 1;drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);drv->if_indices = drv->default_if_indices;drv->if_indices_reason = drv->default_if_indices_reason;drv->first_bss = os_zalloc(sizeof(*drv->first_bss));if (!drv->first_bss) {os_free(drv);return NULL;}bss = drv->first_bss;bss->drv = drv;bss->ctx = ctx;os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));drv->monitor_ifidx = -1;drv->monitor_sock = -1;drv->eapol_tx_sock = -1;drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;if (nl80211_init_bss(bss))goto failed;if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))goto failed;drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);if (drv->eapol_tx_sock < 0)goto failed;if (drv->data_tx_status) {int enabled = 1;if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,&enabled, sizeof(enabled)) < 0) {wpa_printf(MSG_DEBUG,"nl80211: wifi status sockopt failed\n");drv->data_tx_status = 0;if (!drv->use_monitor)drv->capa.flags &=~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;} else {eloop_register_read_sock(drv->eapol_tx_sock,wpa_driver_nl80211_handle_eapol_tx_status,drv, NULL);}}if (drv->global) {nl80211_check_global(drv->global);dl_list_add(&drv->global->interfaces, &drv->list);drv->in_interface_list = 1;}return bss;failed:wpa_driver_nl80211_deinit(bss);return NULL;
}
不是很看得懂了。、、
2.流程梳理
真正创建sta的地方HalDeviceManager
createStaIface - > createIface - > createIfaceIfPossible - > executeChipReconfiguration - > configureChip
wifi_chip.cpp
WifiStatus WifiChip::configureChipInternal(/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,ChipModeId mode_id) {if (!isValidModeId(mode_id)) {return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);}if (mode_id == current_mode_id_) {LOG(DEBUG) << "Already in the specified mode " << mode_id;return createWifiStatus(WifiStatusCode::SUCCESS);}WifiStatus status = handleChipConfiguration(lock, mode_id);if (status.code != WifiStatusCode::SUCCESS) {for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onChipReconfigureFailure(status).isOk()) {LOG(ERROR)<< "Failed to invoke onChipReconfigureFailure callback";}}return status;}for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onChipReconfigured(mode_id).isOk()) {LOG(ERROR) << "Failed to invoke onChipReconfigured callback";}}current_mode_id_ = mode_id;LOG(INFO) << "Configured chip in mode " << mode_id;return status;
}WifiStatus WifiChip::handleChipConfiguration(/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,ChipModeId mode_id) {// If the chip is already configured in a different mode, stop// the legacy HAL and then start it after firmware mode change.if (isValidModeId(current_mode_id_)) {LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_<< " to mode " << mode_id;invalidateAndRemoveAllIfaces();legacy_hal::wifi_error legacy_status =legacy_hal_.lock()->stop(lock, []() {});if (legacy_status != legacy_hal::WIFI_SUCCESS) {LOG(ERROR) << "Failed to stop legacy HAL: "<< legacyErrorToString(legacy_status);return createWifiStatusFromLegacyError(legacy_status);}}// Firmware mode change not needed for V2 devices.bool success = true;if (mode_id == kV1StaChipModeId) {success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);} else if (mode_id == kV1ApChipModeId) {success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);}if (!success) {return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);}legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();if (legacy_status != legacy_hal::WIFI_SUCCESS) {LOG(ERROR) << "Failed to start legacy HAL: "<< legacyErrorToString(legacy_status);return createWifiStatusFromLegacyError(legacy_status);}// Every time the HAL is restarted, we need to register the// radio mode change callback.WifiStatus status = registerRadioModeChangeCallback();if (status.code != WifiStatusCode::SUCCESS) {// This probably is not a critical failure?LOG(ERROR) << "Failed to register radio mode change callback";}return createWifiStatus(WifiStatusCode::SUCCESS);
}
之后会调用到legacy_hal_的start方法
wifi_legacy_hal.cpp
wifi_error WifiLegacyHal::start() {// Ensure that we're starting in a good state.CHECK(global_func_table_.wifi_initialize && !global_handle_ &&iface_name_to_handle_.empty() && !awaiting_event_loop_termination_);if (is_started_) {LOG(DEBUG) << "Legacy HAL already started";return WIFI_SUCCESS;}LOG(DEBUG) << "Waiting for the driver ready";wifi_error status = global_func_table_.wifi_wait_for_driver_ready();if (status == WIFI_ERROR_TIMED_OUT) {LOG(ERROR) << "Timed out awaiting driver ready";return status;}LOG(DEBUG) << "Starting legacy HAL";if (!iface_tool_.SetWifiUpState(true)) {LOG(ERROR) << "Failed to set WiFi interface up";return WIFI_ERROR_UNKNOWN;}status = global_func_table_.wifi_initialize(&global_handle_);if (status != WIFI_SUCCESS || !global_handle_) {LOG(ERROR) << "Failed to retrieve global handle";return status;}std::thread(&WifiLegacyHal::runEventLoop, this).detach();status = retrieveIfaceHandles();if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) {LOG(ERROR) << "Failed to retrieve wlan interface handle";return status;}LOG(DEBUG) << "Legacy HAL start complete";is_started_ = true;return WIFI_SUCCESS;
}
frameworks/opt/net/wifi/libwifi_system_iface/interface_tool.cpp
bool InterfaceTool::SetUpState(const char* if_name, bool request_up) {base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));if (sock.get() < 0) {LOG(ERROR) << "Failed to open socket to set up/down state ("<< strerror(errno) << ")";return false;}struct ifreq ifr;if (!GetIfState(if_name, sock.get(), &ifr)) {return false; // logging done internally}const bool currently_up = ifr.ifr_flags & IFF_UP;if (currently_up == request_up) {return true;}if (request_up) {ifr.ifr_flags |= IFF_UP;} else {ifr.ifr_flags &= ~IFF_UP;}if (TEMP_FAILURE_RETRY(ioctl(sock.get(), SIOCSIFFLAGS, &ifr)) != 0) {LOG(ERROR) << "Could not set interface flags for " << if_name<< " (" << strerror(errno) << ")";return false;}return true;
}bool InterfaceTool::SetWifiUpState(bool request_up) {return SetUpState(kWlan0InterfaceName, request_up);
}
这边看起来是通过ioctl下发命令将iface(默认wlan0)启动起来,这里原生代码写的不大好,既然能接收ifacename,为何不继续往下传呢。
3. 总结
legacy hal start的时候会将iface创建起来。
贴一下百度到的legacy hal是个啥
HAL_legacy:旧式的HAL是一个模块,采用 共享库形式,在编译时会调用到。由于采用function
call形式调用,因此可被多个进程使用,但会被mapping到多个进程空间中,造 成浪费,同时需要考虑代码能否安全重入的问题(thread safe)。
HAL:新式的HAL采用HAL module和HAL stub结合形式,HAL stub不是一个share library,编译时上层只拥有访问HAL stub的函数指针,并不需要HAL stub。上层通过HAL module提供的统一接口获取并操作HAL stub,so文件只会被mapping到一个进程,也不存在重复mapping和重入问题。
(一百五十一)Android P 真正创建sta iface的地方相关推荐
- Kubernetes详解(五十一)——Kubernetes用户创建
今天继续给大家介绍Linux运维相关知识,本文主要内容是Kubernetes用户创建. 在上文Kubernetes详解(五十)--Kubernetes权限配置中,我们介绍了Kubernetes的con ...
- Android开发笔记(一百五十一)WebView与JavaScript交互的四种形式
WebView如果作为简单的网页浏览器,对于一般的浏览行为来说,已经足够了.可做为企业开发者,你的App通常要嵌入自家公司的网页,如此一来,还得考虑App与Web之间的消息传递,这就涉及到App的原生 ...
- 67键键盘如何输出`和~符号(一百五十一)
1.使用需求 因为67键键盘符合黄金分割,看上去特别舒服,但是在使用67键蓝牙键盘的时候,因为最上一排没有F1.F2...等,所以需要输出F1.F2需要借助Fn键 . 但是需要输出的特殊的" ...
- Kubernetes详解(五十三)——Kubernetes Role创建和Rolebinding
今天继续给大家介绍Linux运维相关知识,本文主要内容是Kubernetes Role创建和Rolebinding. 一.Kubernetes Role创建 首先,我们先来创建一个Role.我们可以通 ...
- Gradle 2.0 用户指南翻译——第五十一章. 发布工件
本文禁止w3cschool转载! 翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc . 本文翻译所在分支:https://github.com/m ...
- OpenCV学习笔记(五十一)——imge stitching图像拼接stitching OpenCV学习笔记(五十二)——号外:OpenCV 2.4.1 又出来了。。。。。 OpenCV学习笔记(五
OpenCV学习笔记(五十一)--imge stitching图像拼接stitching stitching是OpenCV2.4.0一个新模块,功能是实现图像拼接,所有的相关函数都被封装在Stitch ...
- 创建构建方法android,如何快速创建并发布一个 Android 库
一. 前言 最近经常看到各种大神的库,发现用起来非常方便,自己研究了一下,来写个库发布一下,让自己写代码更加方便一点,自己封装了基本的开发工具类.也是搜集了各位大神的优秀代码总结的. 二.必要的准备工 ...
- Android 渗透测试学习手册 第五章 Android 取证
第五章 Android 取证 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 5.1 取证类型 取证是使用不同的手动和自动方法从设备中提取和分析数据.它可以大致分为两 ...
- JavaScript学习(五十一)—实训题
JavaScript学习(五十一)-实训题 实训1 定义一个长方形的构造函数(有参数,通过参数给属性赋值)属性:长.宽方法:面积.周长通过这个构造方法创建3个对象,计算面积和周长 实训2 定义创建等边 ...
- 频谱仪的更改ip_【正点原子FPGA连载】第五十一章 基于FFT IP核的音频频谱仪-摘自【正点原子】开拓者 FPGA 开发指南 (amobbs.com 阿莫电子论坛)...
本帖最后由 正点原子 于 2020-10-24 15:19 编辑 203429z6c3os33t8albi33.png (66.36 KB) 2019-7-28 15:14 上传 第五十一章 基于FF ...
最新文章
- Win7环境下VS2010配置Cocos2d-x-2.1.4最新版本的开发环境(亲测)
- 体育场[带权并查集]
- mysql每秒57000_MySQL 性能:使用 MySQL 5.7 实现每秒 50 万查询
- Java程序员该如何学习才能成长为一名优秀的架构师
- python怎么在运行中查看执行状态,Python程序运行时查看对象状态怎样设计才能实现...
- linux下为php开启oci8扩展(ubuntu14亲测可用)
- Scrapy框架(持久化,去重,深度控制,cookie)
- img标签过滤加fs模块实现图片文件缓存
- (已更新)婚礼类小程序前端界面模板源码
- php jmail 乱码,Jmail发送邮件与带附件乱码解决办法分享
- 庆祝北大“如何制作MOOC”课程取得优秀成绩
- Vanilla JS——最轻快的JavaScript框架
- DEFCON GROUP 010上竟玩了这些好玩的东西!
- Cross_entropy和softmax
- android studio 遇到 app error launching怎么办?
- fatal remote does not appear to be a git repository
- mysql 查询不等于空的数据查询
- 大工18秋计算机1答案,大工18秋《专业英语(计算机英语)》在线作业1.docx
- python开发环境部署以及调试教程
- 【微软chatGPT版bing上线了,使用体验如何,符合你的需求吗?】