记一次rk平台热点打开流程追踪记录
问题描述
rk平台偶现热点打开失败,错误日志如下:
1
2
3
4
5
6
7
8
9
10
11I/android.hardware.wifi@1.0-service: Starting legacy HAL E/android.hardware.wifi@1.0-service: Could not set interface flags for wlan0 (Operation not permitted) E/android.hardware.wifi@1.0-service: Failed to set WiFi interface up E/android.hardware.wifi@1.0-service: Failed to start legacy HAL: UNKNOWN E/HalDevMgr: executeChipReconfiguration: configureChip error: 9 (unknown) E/WifiVendorHal: Failed to create AP iface E/WifiNative: Failed to create AP iface in vendor HAL E/SoftApManager: setup failure when creating ap interface. V/WifiManager: SoftApCallbackProxy: onStateChanged: state=14, failureReason=0 E/WifiController: SoftAP start failed
故借此机会准备从Java层开始学习热点的打开流程
开始
1.首先,我们要打开热点,调用是ConnectivityManager中的如下方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback, Handler handler) { Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null."); ResultReceiver wrappedCallback = new ResultReceiver(handler) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { if (resultCode == TETHER_ERROR_NO_ERROR) { callback.onTetheringStarted(); } else { callback.onTetheringFailed(); } } }; try { String pkgName = mContext.getOpPackageName(); Log.i(TAG, "startTethering caller:" + pkgName); mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName); } catch (RemoteException e) { Log.e(TAG, "Exception trying to start tethering.", e); wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null); } }
此方法有四个参数:
type:热点类型,有三种TETHERING_WIFI、TETHERING_USB、TETHERING_BLUETOOTH(一般我们用到的个人热点就是TETHERING_WIFI)
showProvisioningUi:当设置为true是,将展示一个类似使用帮助的页面(需要厂商自己实现)
callback:热点打开结果的回调
handler:可以指定执行上面回调函数的线程
2.找到ConnectivityService的startTethering方法
1
2
3
4
5
6
7
8
9
10
11@Override public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi, String callerPkg) { ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); if (!isTetheringSupported()) { receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null); return; } mTethering.startTethering(type, receiver, showProvisioningUi); }
显示权限检查,注释已经写的很明白了,之后判断是否支持热点,之后就调到了Tethering中的startTethering方法
1
2
3
4
5
6
7
8
9
10
11
12
13public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) { if (!isTetherProvisioningRequired()) {//当没有定义热点UI时就会直接打开热点 enableTetheringInternal(type, true, receiver); return; } if (showProvisioningUi) { runUiTetherProvisioningAndEnable(type, receiver); } else { runSilentTetherProvisioningAndEnable(type, receiver); } }
接下来看enableTetheringInternal方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32/** * Enables or disables tethering for the given type. This should only be called once * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks * for the specified interface. */ private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) { boolean isProvisioningRequired = enable && isTetherProvisioningRequired(); int result; switch (type) { case TETHERING_WIFI: result = setWifiTethering(enable); if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) { scheduleProvisioningRechecks(type); } sendTetherResult(receiver, result); break; case TETHERING_USB: result = setUsbTethering(enable); if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) { scheduleProvisioningRechecks(type); } sendTetherResult(receiver, result); break; case TETHERING_BLUETOOTH: setBluetoothTethering(enable, receiver); break; default: Log.w(TAG, "Invalid tether type."); sendTetherResult(receiver, TETHER_ERROR_UNKNOWN_IFACE); } }
主要看TETHERING_WIFI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18private int setWifiTethering(final boolean enable) { int rval = TETHER_ERROR_MASTER_ERROR; final long ident = Binder.clearCallingIdentity(); try { synchronized (mPublicSync) { mWifiTetherRequested = enable; final WifiManager mgr = getWifiManager(); if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) || (!enable && mgr.stopSoftAp())) { rval = TETHER_ERROR_NO_ERROR; } } } finally { Binder.restoreCallingIdentity(ident); } return rval; }
3.找到startSoftAp的实现,在WifiServiceImpl.java中
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40/** * see {@link android.net.wifi.WifiManager#startSoftAp(WifiConfiguration)} * @param wifiConfig SSID, security and channel details as part of WifiConfiguration * @return {@code true} if softap start was triggered * @throws SecurityException if the caller does not have permission to start softap */ @Override public boolean startSoftAp(WifiConfiguration wifiConfig) { // NETWORK_STACK is a signature only permission. enforceNetworkStackPermission(); mLog.info("startSoftAp uid=%").c(Binder.getCallingUid()).flush(); synchronized (mLocalOnlyHotspotRequests) { // If a tethering request comes in while we have LOHS running (or requested), call stop // for softap mode and restart softap with the tethering config. if (!mLocalOnlyHotspotRequests.isEmpty()) { stopSoftApInternal(); } return startSoftApInternal(wifiConfig, WifiManager.IFACE_IP_MODE_TETHERED); } } /** * Internal method to start softap mode. Callers of this method should have already checked * proper permissions beyond the NetworkStack permission. */ private boolean startSoftApInternal(WifiConfiguration wifiConfig, int mode) { mLog.trace("startSoftApInternal uid=% mode=%") .c(Binder.getCallingUid()).c(mode).flush(); // null wifiConfig is a meaningful input for CMD_SET_AP if (wifiConfig == null || WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) { SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig); mWifiController.sendMessage(CMD_SET_AP, 1, 0, softApConfig); return true; } Slog.e(TAG, "Invalid WifiConfiguration"); return false; }
4.接着到WifiController.java这是个状态机,真正操作打开热点是在WifiStateMachinePrime.java中:
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachinePrime.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/** * Method to enable soft ap for wifi hotspot. * * The supplied SoftApModeConfiguration includes the target softap WifiConfiguration (or null if * the persisted config is to be used) and the target operating mode (ex, * {@link WifiManager.IFACE_IP_MODE_TETHERED} {@link WifiManager.IFACE_IP_MODE_LOCAL_ONLY}). * * @param wifiConfig SoftApModeConfiguration for the hostapd softap */ public void enterSoftAPMode(@NonNull SoftApModeConfiguration wifiConfig) { mHandler.post(() -> { startSoftAp(wifiConfig); }); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18private void startSoftAp(SoftApModeConfiguration softapConfig) { Log.d(TAG, "Starting SoftApModeManager"); WifiConfiguration config = softapConfig.getWifiConfiguration(); if (config != null && config.SSID != null) { Log.d(TAG, "Passing config to SoftApManager! " + config); } else { config = null; } SoftApCallbackImpl callback = new SoftApCallbackImpl(); ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softapConfig); callback.setActiveModeManager(manager); manager.start(); mActiveModeManagers.add(manager); updateBatteryStatsWifiState(true); }
5.找到SoftApManager.java的start()方法:
frameworks/opt/net/wifi/service/java/com/android/server/wifi/SoftApManager.java
1
2
3
4
5
6
7/** * Start soft AP with the supplied config. */ public void start() { mStateMachine.sendMessage(SoftApStateMachine.CMD_START, mApConfig); }
又一个状态机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49private class IdleState extends State { @Override public void enter() { mApInterfaceName = null; mIfaceIsUp = false; } @Override public boolean processMessage(Message message) { switch (message.what) { case CMD_START: Log.e(TAG, "CMD_START."); mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode( mWifiNativeInterfaceCallback); if (TextUtils.isEmpty(mApInterfaceName)) { Log.e(TAG, "setup failure when creating ap interface."); updateApState(WifiManager.WIFI_AP_STATE_FAILED, WifiManager.WIFI_AP_STATE_DISABLED, WifiManager.SAP_START_FAILURE_GENERAL); mWifiMetrics.incrementSoftApStartResult( false, WifiManager.SAP_START_FAILURE_GENERAL); break; } updateApState(WifiManager.WIFI_AP_STATE_ENABLING, WifiManager.WIFI_AP_STATE_DISABLED, 0); int result = startSoftAp((WifiConfiguration) message.obj); if (result != SUCCESS) { int failureReason = WifiManager.SAP_START_FAILURE_GENERAL; if (result == ERROR_NO_CHANNEL) { failureReason = WifiManager.SAP_START_FAILURE_NO_CHANNEL; } updateApState(WifiManager.WIFI_AP_STATE_FAILED, WifiManager.WIFI_AP_STATE_ENABLING, failureReason); stopSoftAp(); mWifiMetrics.incrementSoftApStartResult(false, failureReason); break; } transitionTo(mStartedState); break; default: // Ignore all other commands. break; } return HANDLED; } }
6.setupInterfaceForSoftApMode方法,此处就比较重要了,需要逐条分析:
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51/** * Setup an interface for Soft AP mode operations. * * This method configures an interface in AP mode in all the native daemons * (wificond, wpa_supplicant & vendor HAL). * * @param interfaceCallback Associated callback for notifying status changes for the iface. * @return Returns the name of the allocated interface, will be null on failure. */ public String setupInterfaceForSoftApMode(@NonNull InterfaceCallback interfaceCallback) { Log.e(TAG,"setupInterfaceForSoftApMode"); synchronized (mLock) { if (!startHal()) { Log.e(TAG, "Failed to start Hal"); mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); return null; } Log.e(TAG, "liyang Hal start success"); Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_AP); if (iface == null) { Log.e(TAG, "Failed to allocate new AP iface"); return null; } iface.externalListener = interfaceCallback; iface.name = createApIface(iface); if (TextUtils.isEmpty(iface.name)) { Log.e(TAG, "Failed to create AP iface in vendor HAL"); mIfaceMgr.removeIface(iface.id); mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); return null; } if (mWificondControl.setupInterfaceForSoftApMode(iface.name) == null) { Log.e(TAG, "Failed to setup iface in wificond on " + iface); teardownInterface(iface.name); mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond(); return null; } iface.networkObserver = new NetworkObserverInternal(iface.id); if (!registerNetworkObserver(iface.networkObserver)) { Log.e(TAG, "Failed to register network observer on " + iface); teardownInterface(iface.name); return null; } // Just to avoid any race conditions with interface state change callbacks, // update the interface state before we exit. onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); Log.i(TAG, "Successfully setup " + iface); return iface.name; } }
7先看startHal()方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/** Helper method invoked to start supplicant if there were no ifaces */ private boolean startHal() { synchronized (mLock) { if (!mIfaceMgr.hasAnyIface()) { if (mWifiVendorHal.isVendorHalSupported()) { if (!mWifiVendorHal.startVendorHal()) { Log.e(TAG, "Failed to start vendor HAL"); return false; } } else { Log.i(TAG, "Vendor Hal not supported, ignoring start."); } } return true; } }
首次进来,还未调用 allocateIface 方法,所以 mIfaceMgr.hasAnyIface() 为 false,
同时mWifiVendorHal.isVendorHalSupported()也必然为true,接着就到了WifiVendorHal.java中:
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/** * Bring up the HIDL Vendor HAL and configure for AP (Access Point) mode * * @return true for success */ public boolean startVendorHalAp() { synchronized (sLock) { if (!startVendorHal()) { return false; } if (TextUtils.isEmpty(createApIface(null))) { stopVendorHal(); return false; } return true; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/** * Bring up the HIDL Vendor HAL. * @return true on success, false otherwise. */ public boolean startVendorHal() { synchronized (sLock) { if (!mHalDeviceManager.start()) { mLog.err("Failed to start vendor HAL").flush(); return false; } mLog.info("Vendor Hal started successfully").flush(); return true; } }
frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java
1
2
3
4
5
6
7
8
9
10
11/** * Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or * the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on * success. * * Note: direct call to HIDL. */ public boolean start() { return startWifi(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46private boolean startWifi() { if (VDBG) Log.d(TAG, "startWifi"); synchronized (mLock) { try { if (mWifi == null) { Log.w(TAG, "startWifi called but mWifi is null!?"); return false; } else { int triedCount = 0; while (triedCount <= START_HAL_RETRY_TIMES) { WifiStatus status = mWifi.start(); if (status.code == WifiStatusCode.SUCCESS) { initIWifiChipDebugListeners(); managerStatusListenerDispatch(); if (triedCount != 0) { Log.d(TAG, "start IWifi succeeded after trying " + triedCount + " times"); } return true; } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) { // Should retry. Hal might still be stopping. Log.e(TAG, "Cannot start IWifi: " + statusString(status) + ", Retrying..."); try { Thread.sleep(START_HAL_RETRY_INTERVAL_MS); } catch (InterruptedException ignore) { // no-op } triedCount++; } else { // Should not retry on other failures. Log.e(TAG, "Cannot start IWifi: " + statusString(status)); return false; } } Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times"); return false; } } catch (RemoteException e) { Log.e(TAG, "startWifi exception: " + e); return false; } } }
从 mWifi.start() 开始就到了native层
hardware/interfaces/wifi/1.2/default/wifi.cpp
1
2
3
4
5Return<void> Wifi::start(start_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal, hidl_status_cb); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30WifiStatus Wifi::startInternal() { if (run_state_ == RunState::STARTED) { return createWifiStatus(WifiStatusCode::SUCCESS); } else if (run_state_ == RunState::STOPPING) { return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping"); } WifiStatus wifi_status = initializeModeControllerAndLegacyHal(); if (wifi_status.code == WifiStatusCode::SUCCESS) { // Create the chip instance once the HAL is started. chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_, feature_flags_); run_state_ = RunState::STARTED; for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onStart().isOk()) { LOG(ERROR) << "Failed to invoke onStart callback"; }; } LOG(INFO) << "Wifi HAL started"; } else { for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onFailure(wifi_status).isOk()) { LOG(ERROR) << "Failed to invoke onFailure callback"; } } LOG(ERROR) << "Wifi HAL start failed"; } return wifi_status; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14WifiStatus Wifi::initializeModeControllerAndLegacyHal() { if (!mode_controller_->initialize()) { LOG(ERROR) << "Failed to initialize firmware mode controller"; return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); } legacy_hal::wifi_error legacy_status = legacy_hal_->initialize(); if (legacy_status != legacy_hal::WIFI_SUCCESS) { LOG(ERROR) << "Failed to initialize legacy HAL: " << legacyErrorToString(legacy_status); return createWifiStatusFromLegacyError(legacy_status); } return createWifiStatus(WifiStatusCode::SUCCESS); }
hardware/interfaces/wifi/1.2/default/wifi_mode_controller.cpp
1
2
3
4
5
6
7
8bool WifiModeController::initialize() { if (!driver_tool_->LoadDriver()) { LOG(ERROR) << "Failed to load WiFi driver"; return false; } return true; }
framework/opt/net/wifi/lbwifi_hal/driver_tool.cpp
1
2
3
4bool DriverTool::LoadDriver() { return ::wifi_load_driver() == 0; }
frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53int wifi_load_driver() { #ifdef WIFI_DRIVER_MODULE_PATH char* wifi_ko_path = NULL ; char* wifi_ko_arg =NULL; int i = 0; int count = 100; if (is_wifi_driver_loaded()) { return 0; } if (wifi_type[0] == 0) { check_wifi_chip_type_string(wifi_type); save_wifi_chip_type(wifi_type); } for (i=0; i< (int)(sizeof(module_list) / sizeof(module_list[0])); i++) { if (!strcmp(wifi_type , module_list[i].wifi_name)) { wifi_ko_path = module_list[i].wifi_module_path; wifi_ko_arg = module_list[i].wifi_module_arg; PLOG(ERROR) << "matched ko file path " << wifi_ko_path; break; } } if (wifi_ko_path == NULL) { PLOG(ERROR) << "falied to find wifi driver for type=" << wifi_type; return -1; } if (strstr(wifi_ko_path, MVL_DRIVER_MODULE_NAME)) { insmod(MLAN_DRIVER_MODULE_PATH, ""); } if (insmod(wifi_ko_path, wifi_ko_arg) < 0) { return -1; } #endif #ifdef WIFI_DRIVER_STATE_CTRL_PARAM if (is_wifi_driver_loaded()) { return 0; } if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1; #endif while (count-- > 0) { if (is_wifi_driver_loaded()) { property_set(DRIVER_PROP_NAME, "ok"); return 0; } usleep(200000); } property_set(DRIVER_PROP_NAME, "timeout"); return -1; }
这里面就开始加载wlan0模块,并通过检测/proc/net/dev节点中是否存在wlan0判断是否加载完成,具体模块的初始化在:
kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48dhd_module_init(void) { int err; int retry = 0; printf("%s: in %sn", __FUNCTION__, dhd_version); DHD_PERIM_RADIO_INIT(); if (firmware_path[0] != '') { strncpy(fw_bak_path, firmware_path, MOD_PARAM_PATHLEN); fw_bak_path[MOD_PARAM_PATHLEN-1] = ''; } if (nvram_path[0] != '') { strncpy(nv_bak_path, nvram_path, MOD_PARAM_PATHLEN); nv_bak_path[MOD_PARAM_PATHLEN-1] = ''; } do { err = dhd_wifi_platform_register_drv(); if (!err) { register_reboot_notifier(&dhd_reboot_notifier); break; } else { DHD_ERROR(("%s: Failed to load the driver, try cnt %dn", __FUNCTION__, retry)); strncpy(firmware_path, fw_bak_path, MOD_PARAM_PATHLEN); firmware_path[MOD_PARAM_PATHLEN-1] = ''; strncpy(nvram_path, nv_bak_path, MOD_PARAM_PATHLEN); nvram_path[MOD_PARAM_PATHLEN-1] = ''; } } while (retry--); dhd_create_to_notifier_skt(); if (err) { DHD_ERROR(("%s: Failed to load driver max retry reached**n", __FUNCTION__)); } else { if (!dhd_download_fw_on_driverload) { dhd_driver_init_done = TRUE; } } printf("%s: Exit err=%dn", __FUNCTION__, err); return err; }
当wlan0模块加载完成后,接着看legacy_hal_->initialize(),初始化hal函数:
hardware/interfaces/wifi/1.2/default/wifi_legacy_hal.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16wifi_error WifiLegacyHal::initialize() { LOG(ERROR) << "Initialize legacy HAL"; // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool // for now is this function call which we can directly call. if (!initHalFuncTableWithStubs(&global_func_table_)) { LOG(ERROR) << "Failed to initialize legacy hal function table with stubs"; return WIFI_ERROR_UNKNOWN; } wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_); if (status != WIFI_SUCCESS) { LOG(ERROR) << "Failed to initialize legacy hal function table"; } return status; }
到此,初始化工作就完成了,下面回头看第 6 点中的 createApIface(iface) 方法
8.创建AP Iface
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/** * Helper function to handle creation of AP iface. * For devices which do not the support the HAL, this will bypass HalDeviceManager & * teardown any existing iface. */ private String createApIface(@NonNull Iface iface) { synchronized (mLock) { if (mWifiVendorHal.isVendorHalSupported()) { return mWifiVendorHal.createApIface( new InterfaceDestoyedListenerInternal(iface.id)); } else { Log.i(TAG, "Vendor Hal not supported, ignoring createApIface."); return handleIfaceCreationWhenVendorHalNotSupported(iface); } } }
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28/** * Create a AP iface using {@link HalDeviceManager}. * * @param destroyedListener Listener to be invoked when the interface is destroyed. * @return iface name on success, null otherwise. */ public String createApIface(InterfaceDestroyedListener destroyedListener) { synchronized (sLock) { IWifiApIface iface = mHalDeviceManager.createApIface( new ApInterfaceDestroyedListenerInternal(destroyedListener), null); if (iface == null) { mLog.err("Failed to create AP iface").flush(); return stringResult(null); } String ifaceName = mHalDeviceManager.getName((IWifiIface) iface); if (TextUtils.isEmpty(ifaceName)) { mLog.err("Failed to get iface name").flush(); return stringResult(null); } if (!retrieveWifiChip((IWifiIface) iface)) { mLog.err("Failed to get wifi chip").flush(); return stringResult(null); } mIWifiApIfaces.put(ifaceName, iface); return ifaceName; } }
frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java
1
2
3
4
5
6
7
8/** * Create AP interface if possible (see createStaIface doc). */ public IWifiApIface createApIface(@Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler) { return (IWifiApIface) createIface(IfaceType.AP, false, destroyedListener, handler); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32private IWifiIface createIface(int ifaceType, boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler) { if (mDbg) { Log.d(TAG, "createIface: ifaceType=" + ifaceType + ", lowPriority=" + lowPriority); } synchronized (mLock) { WifiChipInfo[] chipInfos = getAllChipInfo(); if (chipInfos == null) { Log.e(TAG, "createIface: no chip info found"); stopWifi(); // major error: shutting down return null; } if (!validateInterfaceCache(chipInfos)) { Log.e(TAG, "createIface: local cache is invalid!"); stopWifi(); // major error: shutting down return null; } IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, lowPriority, destroyedListener, handler); if (iface != null) { // means that some configuration has changed if (!dispatchAvailableForRequestListeners()) { return null; // catastrophic failure - shut down } } return iface; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95/** * Performs chip reconfiguration per the input: * - Removes the specified interfaces * - Reconfigures the chip to the new chip mode (if necessary) * - Creates the new interface * * Returns the newly created interface or a null on any error. */ private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData, int ifaceType) { if (mDbg) { Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData + ", ifaceType=" + ifaceType); } synchronized (mLock) { try { // is this a mode change? boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId; if (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded); // first delete interfaces/change modes if (isModeConfigNeeded) { // remove all interfaces pre mode-change // TODO: is this necessary? note that even if we don't want to explicitly // remove the interfaces we do need to call the onDeleted callbacks - which // this does for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) { for (WifiIfaceInfo ifaceInfo: ifaceInfos) { removeIfaceInternal(ifaceInfo.iface); // ignore return value } } WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip( ifaceCreationData.chipModeId); if (status.code != WifiStatusCode.SUCCESS) { Log.e(TAG, "executeChipReconfiguration: configureChip error: " + statusString(status)); return null; } } else { // remove all interfaces on the delete list for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) { removeIfaceInternal(ifaceInfo.iface); // ignore return value } } // create new interface Mutable<WifiStatus> statusResp = new Mutable<>(); Mutable<IWifiIface> ifaceResp = new Mutable<>(); switch (ifaceType) { case IfaceType.STA: ifaceCreationData.chipInfo.chip.createStaIface( (WifiStatus status, IWifiStaIface iface) -> { statusResp.value = status; ifaceResp.value = iface; }); break; case IfaceType.AP: ifaceCreationData.chipInfo.chip.createApIface( (WifiStatus status, IWifiApIface iface) -> { statusResp.value = status; ifaceResp.value = iface; }); break; case IfaceType.P2P: ifaceCreationData.chipInfo.chip.createP2pIface( (WifiStatus status, IWifiP2pIface iface) -> { statusResp.value = status; ifaceResp.value = iface; }); break; case IfaceType.NAN: ifaceCreationData.chipInfo.chip.createNanIface( (WifiStatus status, IWifiNanIface iface) -> { statusResp.value = status; ifaceResp.value = iface; }); break; } if (statusResp.value.code != WifiStatusCode.SUCCESS) { Log.e(TAG, "executeChipReconfiguration: failed to create interface ifaceType=" + ifaceType + ": " + statusString(statusResp.value)); return null; } return ifaceResp.value; } catch (RemoteException e) { Log.e(TAG, "executeChipReconfiguration exception: " + e); return null; } } }
主要看里面的
1
2
3WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip( ifaceCreationData.chipModeId);
这里就又走到了native
hardware/interfaces/wifi/1.2/default/wifi_chip.cpp
1
2
3
4
5
6
7Return<void> WifiChip::configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) { return validateAndCallWithLock( this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::configureChipInternal, hidl_status_cb, mode_id); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31WifiStatus WifiChip::configureChipInternal( /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id) { LOG(INFO) << "configureChipInternal mode: " << mode_id << ", current mode: " << current_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; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44WifiStatus WifiChip::handleChipConfiguration( /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id) { LOG(INFO) << "handleChipConfiguration "; // 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); }
hardware/interfaces/wifi/1.2/default/wifi_legacy_hal.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35wifi_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(INFO) << "Legacy HAL already started"; return WIFI_SUCCESS; } LOG(INFO) << "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(INFO) << "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(INFO) << "Legacy HAL start complete"; is_started_ = true; return WIFI_SUCCESS; }
frameworks/opt/net/wifi/libwifi_system_iface/interface_tool.cpp
1
2
3
4bool InterfaceTool::SetWifiUpState(bool request_up) { return SetUpState(kWlan0InterfaceName, request_up); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33bool 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; }
这里通过ioctl调到了kernel中,具体过程不看了,直接找到实现的位置
kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334static int dhd_open(struct net_device *net) { dhd_info_t *dhd = DHD_DEV_INFO(net); #ifdef TOE uint32 toe_ol; #endif #ifdef BCM_FD_AGGR char iovbuf[WLC_IOCTL_SMLEN]; dbus_config_t config; uint32 agglimit = 0; uint32 rpc_agg = BCM_RPC_TP_DNGL_AGG_DPC; /* host aggr not enabled yet */ #endif /* BCM_FD_AGGR */ int ifidx; int32 ret = 0; #if defined(OOB_INTR_ONLY) uint32 bus_type = -1; uint32 bus_num = -1; uint32 slot_num = -1; wifi_adapter_info_t *adapter = NULL; #endif #if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT) int bytes_written = 0; struct dhd_conf *conf; #endif if (!dhd_download_fw_on_driverload) { if (!dhd_driver_init_done) { DHD_ERROR(("%s: WLAN driver is not initializedn", __FUNCTION__)); return -1; } } printf("%s: Enter %pn", __FUNCTION__, net); DHD_MUTEX_LOCK(); /* Init wakelock */ if (!dhd_download_fw_on_driverload) { if (!(dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { DHD_OS_WAKE_LOCK_INIT(dhd); dhd->dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT; } #ifdef SHOW_LOGTRACE skb_queue_head_init(&dhd->evt_trace_queue); if (!(dhd->dhd_state & DHD_ATTACH_LOGTRACE_INIT)) { ret = dhd_init_logstrs_array(dhd->pub.osh, &dhd->event_data); if (ret == BCME_OK) { dhd_init_static_strs_array(dhd->pub.osh, &dhd->event_data, st_str_file_path, map_file_path); dhd_init_static_strs_array(dhd->pub.osh, &dhd->event_data, rom_st_str_file_path, rom_map_file_path); dhd->dhd_state |= DHD_ATTACH_LOGTRACE_INIT; } } #endif /* SHOW_LOGTRACE */ } #if defined(PREVENT_REOPEN_DURING_HANG) /* WAR : to prevent calling dhd_open abnormally in quick succession after hang event */ if (dhd->pub.hang_was_sent == 1) { DHD_ERROR(("%s: HANG was sent up earliern", __FUNCTION__)); /* Force to bring down WLAN interface in case dhd_stop() is not called * from the upper layer when HANG event is triggered. */ if (!dhd_download_fw_on_driverload && dhd->pub.up == 1) { DHD_ERROR(("%s: WLAN interface is not brought downn", __FUNCTION__)); dhd_stop(net); } else { return -1; } } #endif /* PREVENT_REOPEN_DURING_HANG */ DHD_OS_WAKE_LOCK(&dhd->pub); DHD_PERIM_LOCK(&dhd->pub); dhd->pub.dongle_trap_occured = 0; dhd->pub.hang_was_sent = 0; dhd->pub.hang_reason = 0; dhd->pub.iovar_timeout_occured = 0; #ifdef PCIE_FULL_DONGLE dhd->pub.d3ack_timeout_occured = 0; #endif /* PCIE_FULL_DONGLE */ #ifdef DHD_LOSSLESS_ROAMING dhd->pub.dequeue_prec_map = ALLPRIO; #endif #if 0 /* * Force start if ifconfig_up gets called before START command * We keep WEXT's wl_control_wl_start to provide backward compatibility * This should be removed in the future */ ret = wl_control_wl_start(net); if (ret != 0) { DHD_ERROR(("%s: failed with code %dn", __FUNCTION__, ret)); ret = -1; goto exit; } #endif ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %dn", __FUNCTION__, ifidx)); if (ifidx < 0) { DHD_ERROR(("%s: Error: called with invalid IFn", __FUNCTION__)); ret = -1; goto exit; } if (!dhd->iflist[ifidx]) { DHD_ERROR(("%s: Error: called when IF already deletedn", __FUNCTION__)); ret = -1; goto exit; } if (ifidx == 0) { atomic_set(&dhd->pend_8021x_cnt, 0); if (!dhd_download_fw_on_driverload) { DHD_ERROR(("n%sn", dhd_version)); #ifdef WL_EXT_IAPSTA wl_ext_iapsta_attach_netdev(net, ifidx, dhd->iflist[ifidx]->bssidx); #endif #if defined(USE_INITIAL_SHORT_DWELL_TIME) g_first_broadcast_scan = TRUE; #endif #if defined(BT_OVER_SDIO) ret = dhd_bus_get(&dhd->pub, WLAN_MODULE); wl_android_set_wifi_on_flag(TRUE); #else ret = wl_android_wifi_on(net); #endif /* BT_OVER_SDIO */ if (ret != 0) { DHD_ERROR(("%s : wl_android_wifi_on failed (%d)n", __FUNCTION__, ret)); ret = -1; goto exit; } #if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT) conf = dhd_get_conf(net); if (conf) { wl_android_ext_priv_cmd(net, conf->isam_init, 0, &bytes_written); wl_android_ext_priv_cmd(net, conf->isam_config, 0, &bytes_written); wl_android_ext_priv_cmd(net, conf->isam_enable, 0, &bytes_written); } #endif } #ifdef FIX_CPU_MIN_CLOCK if (dhd_get_fw_mode(dhd) == DHD_FLAG_HOSTAP_MODE) { dhd_init_cpufreq_fix(dhd); dhd_fix_cpu_freq(dhd); } #endif /* FIX_CPU_MIN_CLOCK */ #if defined(OOB_INTR_ONLY) if (dhd->pub.conf->dpc_cpucore >= 0) { dhd_bus_get_ids(dhd->pub.bus, &bus_type, &bus_num, &slot_num); adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num); if (adapter) { printf("%s: set irq affinity hit %dn", __FUNCTION__, dhd->pub.conf->dpc_cpucore); irq_set_affinity_hint(adapter->irq_num, cpumask_of(dhd->pub.conf->dpc_cpucore)); } } #endif if (dhd->pub.busstate != DHD_BUS_DATA) { #ifdef BCMDBUS dhd_set_path(&dhd->pub); DHD_MUTEX_UNLOCK(); wait_event_interruptible_timeout(dhd->adapter->status_event, wifi_get_adapter_status(dhd->adapter, WIFI_STATUS_FW_READY), msecs_to_jiffies(DHD_FW_READY_TIMEOUT)); DHD_MUTEX_LOCK(); if ((ret = dbus_up(dhd->pub.bus)) != 0) { DHD_ERROR(("%s: failed to dbus_up with code %dn", __FUNCTION__, ret)); goto exit; } else { dhd->pub.busstate = DHD_BUS_DATA; } if ((ret = dhd_sync_with_dongle(&dhd->pub)) < 0) { DHD_ERROR(("%s: failed with code %dn", __FUNCTION__, ret)); goto exit; } #else /* try to bring up bus */ DHD_PERIM_UNLOCK(&dhd->pub); ret = dhd_bus_start(&dhd->pub); DHD_PERIM_LOCK(&dhd->pub); if (ret) { DHD_ERROR(("%s: failed with code %dn", __FUNCTION__, ret)); ret = -1; goto exit; } #endif /* !BCMDBUS */ } #ifdef WL_EXT_IAPSTA wl_ext_iapsta_attach_name(net, ifidx); #endif if (dhd_download_fw_on_driverload) { if (dhd->pub.conf->deepsleep) dhd_deepsleep(dhd, 0); } #ifdef BCM_FD_AGGR config.config_id = DBUS_CONFIG_ID_AGGR_LIMIT; memset(iovbuf, 0, sizeof(iovbuf)); bcm_mkiovar("rpc_dngl_agglimit", (char *)&agglimit, 4, iovbuf, sizeof(iovbuf)); if (!dhd_wl_ioctl_cmd(&dhd->pub, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) { agglimit = *(uint32 *)iovbuf; config.aggr_param.maxrxsf = agglimit >> BCM_RPC_TP_AGG_SF_SHIFT; config.aggr_param.maxrxsize = agglimit & BCM_RPC_TP_AGG_BYTES_MASK; DHD_ERROR(("rpc_dngl_agglimit %x : sf_limit %d bytes_limit %dn", agglimit, config.aggr_param.maxrxsf, config.aggr_param.maxrxsize)); if (bcm_rpc_tp_set_config(dhd->pub.info->rpc_th, &config)) { DHD_ERROR(("set tx/rx queue size and buffersize failedn")); } } else { DHD_ERROR(("get rpc_dngl_agglimit failedn")); rpc_agg &= ~BCM_RPC_TP_DNGL_AGG_DPC; } /* Set aggregation for TX */ bcm_rpc_tp_agg_set(dhd->pub.info->rpc_th, BCM_RPC_TP_HOST_AGG_MASK, rpc_agg & BCM_RPC_TP_HOST_AGG_MASK); /* Set aggregation for RX */ memset(iovbuf, 0, sizeof(iovbuf)); bcm_mkiovar("rpc_agg", (char *)&rpc_agg, sizeof(rpc_agg), iovbuf, sizeof(iovbuf)); if (!dhd_wl_ioctl_cmd(&dhd->pub, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) { dhd->pub.info->fdaggr = 0; if (rpc_agg & BCM_RPC_TP_HOST_AGG_MASK) dhd->pub.info->fdaggr |= BCM_FDAGGR_H2D_ENABLED; if (rpc_agg & BCM_RPC_TP_DNGL_AGG_MASK) dhd->pub.info->fdaggr |= BCM_FDAGGR_D2H_ENABLED; } else { DHD_ERROR(("%s(): Setting RX aggregation failed %dn", __FUNCTION__, ret)); } #endif /* BCM_FD_AGGR */ #ifdef BT_OVER_SDIO if (dhd->pub.is_bt_recovery_required) { DHD_ERROR(("%s: Send Hang Notification 2 to BTn", __FUNCTION__)); bcmsdh_btsdio_process_dhd_hang_notification(TRUE); } dhd->pub.is_bt_recovery_required = FALSE; #endif /* dhd_sync_with_dongle has been called in dhd_bus_start or wl_android_wifi_on */ memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); #ifdef TOE /* Get current TOE mode from dongle */ if (dhd_toe_get(dhd, ifidx, &toe_ol) >= 0 && (toe_ol & TOE_TX_CSUM_OL) != 0) { dhd->iflist[ifidx]->net->features |= NETIF_F_IP_CSUM; } else { dhd->iflist[ifidx]->net->features &= ~NETIF_F_IP_CSUM; } #endif /* TOE */ #if defined(DHD_LB_RXP) __skb_queue_head_init(&dhd->rx_pend_queue); if (dhd->rx_napi_netdev == NULL) { dhd->rx_napi_netdev = dhd->iflist[ifidx]->net; memset(&dhd->rx_napi_struct, 0, sizeof(struct napi_struct)); netif_napi_add(dhd->rx_napi_netdev, &dhd->rx_napi_struct, dhd_napi_poll, dhd_napi_weight); DHD_INFO(("%s napi<%p> enabled ifp->net<%p,%s>n", __FUNCTION__, &dhd->rx_napi_struct, net, net->name)); napi_enable(&dhd->rx_napi_struct); DHD_INFO(("%s load balance init rx_napi_structn", __FUNCTION__)); skb_queue_head_init(&dhd->rx_napi_queue); } /* rx_napi_netdev == NULL */ #endif /* DHD_LB_RXP */ #if defined(DHD_LB_TXP) /* Use the variant that uses locks */ skb_queue_head_init(&dhd->tx_pend_queue); #endif /* DHD_LB_TXP */ #if defined(WL_CFG80211) if (unlikely(wl_cfg80211_up(net))) { DHD_ERROR(("%s: failed to bring up cfg80211n", __FUNCTION__)); ret = -1; goto exit; } if (!dhd_download_fw_on_driverload) { #ifdef ARP_OFFLOAD_SUPPORT dhd->pend_ipaddr = 0; if (!dhd_inetaddr_notifier_registered) { dhd_inetaddr_notifier_registered = TRUE; register_inetaddr_notifier(&dhd_inetaddr_notifier); } #endif /* ARP_OFFLOAD_SUPPORT */ #if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) if (!dhd_inet6addr_notifier_registered) { dhd_inet6addr_notifier_registered = TRUE; register_inet6addr_notifier(&dhd_inet6addr_notifier); } #endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ } argos_register_notifier_init(net); #if defined(NUM_SCB_MAX_PROBE) dhd_set_scb_probe(&dhd->pub); #endif /* NUM_SCB_MAX_PROBE */ #endif /* WL_CFG80211 */ } /* Allow transmit calls */ netif_start_queue(net); dhd->pub.up = 1; OLD_MOD_INC_USE_COUNT; #ifdef BCMDBGFS dhd_dbgfs_init(&dhd->pub); #endif exit: if (ret) { dhd_stop(net); } DHD_PERIM_UNLOCK(&dhd->pub); DHD_OS_WAKE_UNLOCK(&dhd->pub); DHD_MUTEX_UNLOCK(); printf("%s: Exit ret=%dn", __FUNCTION__, ret); return ret; }
这个方法是真的长,到此就找到了上面热点打不开报错的位置:
1
2
3
4
5
6
7if (!dhd_download_fw_on_driverload) { if (!dhd_driver_init_done) { DHD_ERROR(("%s: WLAN driver is not initializedn", __FUNCTION__)); return -1; } }
那么dhd_driver_init_done是在什么时候被设置为true的呢,看这个类里面的dhd_module_init方法,也就是说在第7点的startHal()方法;流程中被置为true的,而之前有分析了,startHal()成功的判断条件是/proc/net/dev节点中存在wlan0,那么什么时候开始这个判断成立的呢,看dhd_module_init(void)的register_reboot_notifier(&dhd_reboot_notifier),在这个方法流程中就会初始化wlan0,那么这就导致了,同步问题,wlan0虽然初始化完成了,但dhd_driver_init_done还未被设置,导致上面的报错
解决办法
为 **dhd_module_init(void)和dhd_open(struct net_device *net)**这两个方法添加互斥锁,已解决同步问题,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17DEFINE_MUTEX(_wlan_init_mutex_lock_); #define WLAN_MUTEX_LOCK() do { if (mutex_is_locked(&_wlan_init_mutex_lock_) == 0) { printf("%s : no wlan mutex held. set lockn", __FUNCTION__); } else { printf("%s : wlan mutex is locked!. wait for unlockingn", __FUNCTION__); } mutex_lock(&_wlan_init_mutex_lock_); } while (0) #define WLAN_MUTEX_UNLOCK() do { mutex_unlock(&_wlan_init_mutex_lock_); printf("%s : the wlan lock is released.n", __FUNCTION__); } while (0)
1
2
3
4
5
6
7
8
9
10
11if (!dhd_download_fw_on_driverload) { WLAN_MUTEX_LOCK(); if (!dhd_driver_init_done) { DHD_ERROR(("%s: WLAN driver is not initializedn", __FUNCTION__)); WLAN_MUTEX_UNLOCK(); return -1; }else{ WLAN_MUTEX_UNLOCK(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17static int dhd_module_init(void) { int err; int retry = 0; WLAN_MUTEX_LOCK(); printf("%s: in %sn", __FUNCTION__, dhd_version); DHD_PERIM_RADIO_INIT(); ............ ............ ............ printf("%s: Exit err=%dn", __FUNCTION__, err); WLAN_MUTEX_UNLOCK(); return err; }
最后
以上就是悦耳唇膏最近收集整理的关于记一次rk平台热点打开流程追踪记录记一次rk平台热点打开流程追踪记录的全部内容,更多相关记一次rk平台热点打开流程追踪记录记一次rk平台热点打开流程追踪记录内容请搜索靠谱客的其他文章。
发表评论 取消回复