From 52947fbc7ebaa2657ee0d050703dcb72a07d1b76 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 18 Nov 2016 11:38:07 -0800 Subject: wifi: Implement chip mode combinations This is pretty hardcoded for now. We expose 2 chip modes: 1. STA mode: 1 STA and 1 P2P or NAN iface. 2. AP mode: 1 AP iface. Implement the chip mode configuration related HIDL methods in WifiChip and integrate WifiModeController. These is some change in the order of calls invoked within the implementation to accomodate the firmware reload: a. Since the legacy HAL needs to reinitialized after firmware reload, we can no longer do this in IWifi.start(). So, we'll defer this to IWifiChip.configureChip() now. b. Refactor IWifi.startInternal() and IWifi.stopInternal() to pull out the actual implementation into a separate helper functions and let it invoke the required callbacks. Bug: 31997422 Bug: 32018162 Test: Compiles Change-Id: I461687d7ee92398bc47321e1baca609db65c7991 --- wifi/1.0/default/wifi.cpp | 103 ++++++++++++++++++++++++++--------------- wifi/1.0/default/wifi.h | 5 ++ wifi/1.0/default/wifi_chip.cpp | 97 ++++++++++++++++++++++++++++++++++---- wifi/1.0/default/wifi_chip.h | 9 +++- 4 files changed, 164 insertions(+), 50 deletions(-) (limited to 'wifi') diff --git a/wifi/1.0/default/wifi.cpp b/wifi/1.0/default/wifi.cpp index 19f7e53bd..30adcc04b 100644 --- a/wifi/1.0/default/wifi.cpp +++ b/wifi/1.0/default/wifi.cpp @@ -34,6 +34,7 @@ using hidl_return_util::validateAndCall; Wifi::Wifi() : legacy_hal_(new legacy_hal::WifiLegacyHal()), + mode_controller_(new mode_controller::WifiModeController()), run_state_(RunState::STOPPED) {} bool Wifi::isValid() { @@ -96,25 +97,29 @@ WifiStatus Wifi::startInternal() { return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping"); } - - LOG(INFO) << "Starting HAL"; - legacy_hal::wifi_error legacy_status = legacy_hal_->start(); - if (legacy_status != legacy_hal::WIFI_SUCCESS) { - LOG(ERROR) << "Failed to start Wifi HAL: " - << legacyErrorToString(legacy_status); - return createWifiStatusFromLegacyError(legacy_status, - "Failed to start HAL"); - } - - // Create the chip instance once the HAL is started. - chip_ = new WifiChip(kChipId, legacy_hal_); - run_state_ = RunState::STARTED; - for (const auto& callback : event_callbacks_) { - if (!callback->onStart().getStatus().isOk()) { - LOG(ERROR) << "Failed to invoke onStart callback"; - }; + WifiStatus wifi_status = initializeLegacyHal(); + if (wifi_status.code == WifiStatusCode::SUCCESS) { + // Create the chip instance once the HAL is started. + chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_); + run_state_ = RunState::STARTED; + for (const auto& callback : event_callbacks_) { + if (!callback->onStart().getStatus().isOk()) { + LOG(ERROR) << "Failed to invoke onStart callback"; + }; + } + for (const auto& callback : event_callbacks_) { + if (!callback->onFailure(wifi_status).getStatus().isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + } else { + for (const auto& callback : event_callbacks_) { + if (!callback->onFailure(wifi_status).getStatus().isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } } - return createWifiStatus(WifiStatusCode::SUCCESS); + return wifi_status; } WifiStatus Wifi::stopInternal() { @@ -124,34 +129,21 @@ WifiStatus Wifi::stopInternal() { return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping"); } - - LOG(INFO) << "Stopping HAL"; - run_state_ = RunState::STOPPING; - const auto on_complete_callback_ = [&]() { - if (chip_.get()) { - chip_->invalidate(); - } - chip_.clear(); - run_state_ = RunState::STOPPED; + WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(); + if (wifi_status.code == WifiStatusCode::SUCCESS) { for (const auto& callback : event_callbacks_) { if (!callback->onStop().getStatus().isOk()) { LOG(ERROR) << "Failed to invoke onStop callback"; }; } - }; - legacy_hal::wifi_error legacy_status = - legacy_hal_->stop(on_complete_callback_); - if (legacy_status != legacy_hal::WIFI_SUCCESS) { - LOG(ERROR) << "Failed to stop Wifi HAL: " - << legacyErrorToString(legacy_status); - WifiStatus wifi_status = - createWifiStatusFromLegacyError(legacy_status, "Failed to stop HAL"); + } else { for (const auto& callback : event_callbacks_) { - callback->onFailure(wifi_status); + if (!callback->onFailure(wifi_status).getStatus().isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } } - return wifi_status; } - return createWifiStatus(WifiStatusCode::SUCCESS); + return wifi_status; } std::pair> Wifi::getChipIdsInternal() { @@ -171,6 +163,41 @@ std::pair> Wifi::getChipInternal(ChipId chip_id) { } return {createWifiStatus(WifiStatusCode::SUCCESS), chip_}; } + +WifiStatus Wifi::initializeLegacyHal() { + LOG(INFO) << "Initializing legacy HAL"; + 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); +} + +WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() { + LOG(INFO) << "Stopping legacy HAL"; + run_state_ = RunState::STOPPING; + const auto on_complete_callback_ = [&]() { + if (chip_.get()) { + chip_->invalidate(); + } + chip_.clear(); + run_state_ = RunState::STOPPED; + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_->stop(on_complete_callback_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL: " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + if (!mode_controller_->deinitialize()) { + LOG(ERROR) << "Failed to deinitialize firmware mode controller"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} } // namespace implementation } // namespace V1_0 } // namespace wifi diff --git a/wifi/1.0/default/wifi.h b/wifi/1.0/default/wifi.h index 7872303a4..40d355256 100644 --- a/wifi/1.0/default/wifi.h +++ b/wifi/1.0/default/wifi.h @@ -25,6 +25,7 @@ #include "wifi_chip.h" #include "wifi_legacy_hal.h" +#include "wifi_mode_controller.h" namespace android { namespace hardware { @@ -62,9 +63,13 @@ class Wifi : public IWifi { std::pair> getChipIdsInternal(); std::pair> getChipInternal(ChipId chip_id); + WifiStatus initializeLegacyHal(); + WifiStatus stopLegacyHalAndDeinitializeModeController(); + // Instance is created in this root level |IWifi| HIDL interface object // and shared with all the child HIDL interface objects. std::shared_ptr legacy_hal_; + std::shared_ptr mode_controller_; RunState run_state_; std::vector> event_callbacks_; sp chip_; diff --git a/wifi/1.0/default/wifi_chip.cpp b/wifi/1.0/default/wifi_chip.cpp index 3ab60524a..2487d9ffd 100644 --- a/wifi/1.0/default/wifi_chip.cpp +++ b/wifi/1.0/default/wifi_chip.cpp @@ -24,6 +24,12 @@ namespace { using android::sp; using android::hardware::hidl_vec; using android::hardware::hidl_string; +using android::hardware::wifi::V1_0::IWifiChip; +using android::hardware::wifi::V1_0::IfaceType; + +constexpr uint32_t kStaChipModeId = 0; +constexpr uint32_t kApChipModeId = 1; +constexpr uint32_t kInvalidModeId = UINT32_MAX; template void invalidateAndClear(sp& iface) { @@ -41,9 +47,15 @@ namespace V1_0 { namespace implementation { using hidl_return_util::validateAndCall; -WifiChip::WifiChip(ChipId chip_id, - const std::weak_ptr legacy_hal) - : chip_id_(chip_id), legacy_hal_(legacy_hal), is_valid_(true) {} +WifiChip::WifiChip( + ChipId chip_id, + const std::weak_ptr legacy_hal, + const std::weak_ptr mode_controller) + : chip_id_(chip_id), + legacy_hal_(legacy_hal), + mode_controller_(mode_controller), + is_valid_(true), + current_mode_id_(kInvalidModeId) {} void WifiChip::invalidate() { invalidateAndRemoveAllIfaces(); @@ -301,19 +313,84 @@ std::pair WifiChip::getCapabilitiesInternal() { std::pair> WifiChip::getAvailableModesInternal() { - // TODO add implementation - return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + // The chip combination supported for current devices is fixed for now with + // 2 separate modes of operation: + // Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN iface operations + // concurrently. + // Mode 2 (AP mode): Will support 1 AP iface operations. + // TODO (b/32997844): Read this from some device specific flags in the + // makefile. + // STA mode iface combinations. + const IWifiChip::ChipIfaceCombinationLimit + sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1}; + const IWifiChip::ChipIfaceCombinationLimit + sta_chip_iface_combination_limit_2 = {{IfaceType::P2P, IfaceType::NAN}, + 1}; + const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = { + {sta_chip_iface_combination_limit_1, sta_chip_iface_combination_limit_2}}; + const IWifiChip::ChipMode sta_chip_mode = {kStaChipModeId, + {sta_chip_iface_combination}}; + // AP mode iface combinations. + const IWifiChip::ChipIfaceCombinationLimit ap_chip_iface_combination_limit = { + {IfaceType::AP}, 1}; + const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = { + {ap_chip_iface_combination_limit}}; + const IWifiChip::ChipMode ap_chip_mode = {kApChipModeId, + {ap_chip_iface_combination}}; + return {createWifiStatus(WifiStatusCode::SUCCESS), + {sta_chip_mode, ap_chip_mode}}; } -WifiStatus WifiChip::configureChipInternal(uint32_t /* mode_id */) { - invalidateAndRemoveAllIfaces(); - // TODO add implementation +WifiStatus WifiChip::configureChipInternal(uint32_t mode_id) { + if (mode_id != kStaChipModeId && mode_id != kApChipModeId) { + 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); + } + // If the chip is already configured in a different mode, stop + // the legacy HAL and then start it after firmware mode change. + if (current_mode_id_ != kInvalidModeId) { + invalidateAndRemoveAllIfaces(); + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop([]() {}); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL: " + << legacyErrorToString(legacy_status); + // TODO(b/33038823): Need to invoke onChipReconfigureFailure() + return createWifiStatusFromLegacyError(legacy_status); + } + } + bool success; + if (mode_id == kStaChipModeId) { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA); + } else { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP); + } + if (!success) { + // TODO(b/33038823): Need to invoke onChipReconfigureFailure() + 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); + // TODO(b/33038823): Need to invoke onChipReconfigureFailure() + return createWifiStatusFromLegacyError(legacy_status); + } + for (const auto& callback : event_callbacks_) { + callback->onChipReconfigured(mode_id); + } + current_mode_id_ = mode_id; return createWifiStatus(WifiStatusCode::SUCCESS); } std::pair WifiChip::getModeInternal() { - // TODO add implementation - return {createWifiStatus(WifiStatusCode::SUCCESS), 0}; + if (current_mode_id_ == kInvalidModeId) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), + current_mode_id_}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_}; } std::pair diff --git a/wifi/1.0/default/wifi_chip.h b/wifi/1.0/default/wifi_chip.h index c1a717303..764445fab 100644 --- a/wifi/1.0/default/wifi_chip.h +++ b/wifi/1.0/default/wifi_chip.h @@ -24,6 +24,7 @@ #include "wifi_ap_iface.h" #include "wifi_legacy_hal.h" +#include "wifi_mode_controller.h" #include "wifi_nan_iface.h" #include "wifi_p2p_iface.h" #include "wifi_rtt_controller.h" @@ -42,8 +43,10 @@ namespace implementation { */ class WifiChip : public IWifiChip { public: - WifiChip(ChipId chip_id, - const std::weak_ptr legacy_hal); + WifiChip( + ChipId chip_id, + const std::weak_ptr legacy_hal, + const std::weak_ptr mode_controller); // HIDL does not provide a built-in mechanism to let the server invalidate // a HIDL interface object after creation. If any client process holds onto // a reference to the object in their context, any method calls on that @@ -156,6 +159,7 @@ class WifiChip : public IWifiChip { ChipId chip_id_; std::weak_ptr legacy_hal_; + std::weak_ptr mode_controller_; std::vector> event_callbacks_; sp ap_iface_; sp nan_iface_; @@ -163,6 +167,7 @@ class WifiChip : public IWifiChip { sp sta_iface_; std::vector> rtt_controllers_; bool is_valid_; + uint32_t current_mode_id_; DISALLOW_COPY_AND_ASSIGN(WifiChip); }; -- cgit v1.2.3