From ddab4bbd9cc529db8a7ff52246b5daf6f6ec2475 Mon Sep 17 00:00:00 2001 From: Sunil Ravi Date: Mon, 3 Feb 2020 22:45:19 -0800 Subject: [PATCH] wifi: Add provision to create/delete dynamic interface(s) This commit does following: create/delete softap interface at runtime, if needed. create/delete station interface at runtime, if needed. Bug: 146539882 Bug: 121156971 Test: Manual - Basic wifi sanity test. Change-Id: I6ab9c9e134d2f09e27283c9e60df885392834de4 Signed-off-by: Vinay Gannevaram --- wifi/1.4/default/hidl_struct_util.cpp | 15 ++++++++++ wifi/1.4/default/hidl_struct_util.h | 2 ++ wifi/1.4/default/wifi_chip.cpp | 30 +++++++++++++++++++ wifi/1.4/default/wifi_legacy_hal.cpp | 35 ++++++++++++++++++++++ wifi/1.4/default/wifi_legacy_hal.h | 8 +++++ wifi/1.4/default/wifi_legacy_hal_stubs.cpp | 2 ++ 6 files changed, 92 insertions(+) diff --git a/wifi/1.4/default/hidl_struct_util.cpp b/wifi/1.4/default/hidl_struct_util.cpp index 4996e358b2..fd1d5b1121 100644 --- a/wifi/1.4/default/hidl_struct_util.cpp +++ b/wifi/1.4/default/hidl_struct_util.cpp @@ -2715,6 +2715,21 @@ bool convertLegacyVectorOfRttResultToHidl( } return true; } + +legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy( + IfaceType hidl_interface_type) { + switch (hidl_interface_type) { + case IfaceType::STA: + return legacy_hal::WIFI_INTERFACE_TYPE_STA; + case IfaceType::AP: + return legacy_hal::WIFI_INTERFACE_TYPE_AP; + case IfaceType::P2P: + return legacy_hal::WIFI_INTERFACE_TYPE_P2P; + case IfaceType::NAN: + return legacy_hal::WIFI_INTERFACE_TYPE_NAN; + } + CHECK(false); +} } // namespace hidl_struct_util } // namespace implementation } // namespace V1_4 diff --git a/wifi/1.4/default/hidl_struct_util.h b/wifi/1.4/default/hidl_struct_util.h index d040c1fd2e..929f877d96 100644 --- a/wifi/1.4/default/hidl_struct_util.h +++ b/wifi/1.4/default/hidl_struct_util.h @@ -65,6 +65,8 @@ legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( bool convertLegacyWifiMacInfosToHidl( const std::vector& legacy_mac_infos, std::vector* hidl_radio_mode_infos); +legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy( + IfaceType hidl_interface_type); // STA iface conversion methods. bool convertLegacyFeaturesToHidlStaCapabilities( diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp index 3498510e2e..4c9fad17bb 100644 --- a/wifi/1.4/default/wifi_chip.cpp +++ b/wifi/1.4/default/wifi_chip.cpp @@ -797,6 +797,15 @@ std::pair> WifiChip::createApIfaceInternal() { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } std::string ifname = allocateApIfaceName(); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->createVirtualInterface( + ifname, + hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP)); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to add interface: " << ifname << " " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } sp iface = new WifiApIface(ifname, legacy_hal_, iface_util_); ap_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { @@ -835,6 +844,12 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { // nan/rtt objects over AP iface. But, there is no harm to do it // here and not make that assumption all over the place. invalidateAndRemoveDependencies(ifname); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << ifname << " " + << legacyErrorToString(legacy_status); + } invalidateAndClear(ap_ifaces_, iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) { @@ -944,6 +959,15 @@ WifiChip::createStaIfaceInternal() { return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; } std::string ifname = allocateStaIfaceName(); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->createVirtualInterface( + ifname, + hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA)); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to add interface: " << ifname << " " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } sp iface = new WifiStaIface(ifname, legacy_hal_, iface_util_); sta_ifaces_.push_back(iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { @@ -979,6 +1003,12 @@ WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) { } // Invalidate & remove any dependent objects first. invalidateAndRemoveDependencies(ifname); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << ifname << " " + << legacyErrorToString(legacy_status); + } invalidateAndClear(sta_ifaces_, iface); for (const auto& callback : event_cb_handler_.getCallbacks()) { if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) { diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.4/default/wifi_legacy_hal.cpp index 3ca3226bd9..a040c89a30 100644 --- a/wifi/1.4/default/wifi_legacy_hal.cpp +++ b/wifi/1.4/default/wifi_legacy_hal.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "hidl_sync_util.h" #include "wifi_legacy_hal.h" @@ -1355,6 +1356,7 @@ wifi_error WifiLegacyHal::retrieveIfaceHandles() { LOG(ERROR) << "Failed to enumerate interface handles"; return status; } + iface_name_to_handle_.clear(); for (int i = 0; i < num_iface_handles; ++i) { std::array iface_name_arr = {}; status = global_func_table_.wifi_get_iface_name( @@ -1421,6 +1423,39 @@ WifiLegacyHal::getGscanCachedResults(const std::string& iface_name) { return {status, std::move(cached_scan_results)}; } +wifi_error WifiLegacyHal::createVirtualInterface(const std::string& ifname, + wifi_interface_type iftype) { + // Create the interface if it doesn't exist. If interface already exist, + // Vendor Hal should return WIFI_SUCCESS. + wifi_error status = global_func_table_.wifi_virtual_interface_create( + global_handle_, ifname.c_str(), iftype); + return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status); +} + +wifi_error WifiLegacyHal::deleteVirtualInterface(const std::string& ifname) { + // Delete the interface if it was created dynamically. + wifi_error status = global_func_table_.wifi_virtual_interface_delete( + global_handle_, ifname.c_str()); + return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status); +} + +wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus( + const std::string& ifname, wifi_error status) { + if (status == WIFI_SUCCESS) { + // refresh list of handlers now. + status = retrieveIfaceHandles(); + } else if (status == WIFI_ERROR_NOT_SUPPORTED) { + // Vendor hal does not implement this API. Such vendor implementations + // are expected to create / delete interface by other means. + + // check if interface exists. + if (if_nametoindex(ifname.c_str())) { + status = retrieveIfaceHandles(); + } + } + return status; +} + void WifiLegacyHal::invalidate() { global_handle_ = nullptr; iface_name_to_handle_.clear(); diff --git a/wifi/1.4/default/wifi_legacy_hal.h b/wifi/1.4/default/wifi_legacy_hal.h index a7b40a05cc..72cf197539 100644 --- a/wifi/1.4/default/wifi_legacy_hal.h +++ b/wifi/1.4/default/wifi_legacy_hal.h @@ -369,6 +369,11 @@ class WifiLegacyHal { wifi_error setCountryCode(const std::string& iface_name, std::array code); + // interface functions. + wifi_error createVirtualInterface(const std::string& ifname, + wifi_interface_type iftype); + wifi_error deleteVirtualInterface(const std::string& ifname); + private: // Retrieve interface handles for all the available interfaces. wifi_error retrieveIfaceHandles(); @@ -380,6 +385,9 @@ class WifiLegacyHal { std::pair> getGscanCachedResults(const std::string& iface_name); void invalidate(); + // Handles wifi (error) status of Virtual interface create/delete + wifi_error handleVirtualInterfaceCreateOrDeleteStatus( + const std::string& ifname, wifi_error status); // Global function table of legacy HAL. wifi_hal_fn global_func_table_; diff --git a/wifi/1.4/default/wifi_legacy_hal_stubs.cpp b/wifi/1.4/default/wifi_legacy_hal_stubs.cpp index bbe470e580..6945b4ca01 100644 --- a/wifi/1.4/default/wifi_legacy_hal_stubs.cpp +++ b/wifi/1.4/default/wifi_legacy_hal_stubs.cpp @@ -139,6 +139,8 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { populateStubFor(&hal_fn->wifi_set_radio_mode_change_handler); populateStubFor(&hal_fn->wifi_set_latency_mode); populateStubFor(&hal_fn->wifi_set_thermal_mitigation_mode); + populateStubFor(&hal_fn->wifi_virtual_interface_create); + populateStubFor(&hal_fn->wifi_virtual_interface_delete); return true; } } // namespace legacy_hal