diff --git a/wifi/1.6/IWifiChip.hal b/wifi/1.6/IWifiChip.hal index eaa2400466..555ec918ac 100644 --- a/wifi/1.6/IWifiChip.hal +++ b/wifi/1.6/IWifiChip.hal @@ -99,4 +99,35 @@ interface IWifiChip extends @1.5::IWifiChip { getUsableChannels_1_6(WifiBand band, bitfield ifaceModeMask, bitfield filterMask) generates (WifiStatus status, vec channels); + + /** + * Retrieve the list of all the possible radio combinations supported by this + * chip. + * + * @return status WifiStatus of the operation. + * Possible status codes: + * |WifiStatusCode.SUCCESS|, + * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.FAILURE_UNKNOWN| + * @return radioCombinationMatrix + * A list of all the possible radio combinations represented by + * |WifiRadioCombinationMatrix|. + * For Example in case of a chip which has two radios, where one radio is + * capable of 2.4GHz 2X2 only and another radio which is capable of either + * 5GHz or 6GHz 2X2, number of possible radio combinations in this case + * are 5 and possible combinations are + * {{{2G 2X2}}, //Standalone 2G + * {{5G 2X2}}, //Standalone 5G + * {{6G 2X2}}, //Standalone 6G + * {{2G 2X2}, {5G 2X2}}, //2G+5G DBS + * {{2G 2X2}, {6G 2X2}}} //2G+6G DBS + * Note: Since this chip doesn’t support 5G+6G simultaneous operation + * as there is only one radio which can support both bands, So it can only + * do MCC 5G+6G. This table should not get populated with possible MCC + * configurations. This is only for simultaneous radio configurations + * (such as standalone, multi band simultaneous or single band simultaneous). + */ + getSupportedRadioCombinationsMatrix() + generates (WifiStatus status, WifiRadioCombinationMatrix radioCombinationMatrix); }; diff --git a/wifi/1.6/default/hidl_struct_util.cpp b/wifi/1.6/default/hidl_struct_util.cpp index 71f98b9ef5..45459e2cd3 100644 --- a/wifi/1.6/default/hidl_struct_util.cpp +++ b/wifi/1.6/default/hidl_struct_util.cpp @@ -367,6 +367,21 @@ uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand hidl_band) { } } +V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band) { + switch (band) { + case legacy_hal::WLAN_MAC_2_4_BAND: + return V1_5::WifiBand::BAND_24GHZ; + case legacy_hal::WLAN_MAC_5_0_BAND: + return V1_5::WifiBand::BAND_5GHZ; + case legacy_hal::WLAN_MAC_6_0_BAND: + return V1_5::WifiBand::BAND_6GHZ; + case legacy_hal::WLAN_MAC_60_0_BAND: + return V1_5::WifiBand::BAND_60GHZ; + default: + return V1_5::WifiBand::BAND_UNSPECIFIED; + } +} + uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask) { uint32_t legacy_iface_mask = 0; if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_STA) { @@ -2905,6 +2920,85 @@ bool convertHidlVectorOfCoexUnsafeChannelToLegacy( return true; } +V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg) { + switch (antenna_cfg) { + case legacy_hal::WIFI_ANTENNA_1X1: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_1X1; + case legacy_hal::WIFI_ANTENNA_2X2: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_2X2; + case legacy_hal::WIFI_ANTENNA_3X3: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_3X3; + case legacy_hal::WIFI_ANTENNA_4X4: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_4X4; + default: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_UNSPECIFIED; + } +} + +bool convertLegacyWifiRadioConfigurationToHidl( + legacy_hal::wifi_radio_configuration* radio_configuration, + V1_6::WifiRadioConfiguration* hidl_radio_configuration) { + if (!hidl_radio_configuration) { + return false; + } + *hidl_radio_configuration = {}; + hidl_radio_configuration->bandInfo = + hidl_struct_util::convertLegacyMacBandToHidlWifiBand(radio_configuration->band); + if (hidl_radio_configuration->bandInfo == V1_5::WifiBand::BAND_UNSPECIFIED) { + LOG(ERROR) << "Unspecified band"; + return false; + } + hidl_radio_configuration->antennaMode = + hidl_struct_util::convertLegacyAntennaConfigurationToHidl( + radio_configuration->antenna_cfg); + return true; +} + +bool convertLegacyRadioCombinationsMatrixToHidl( + legacy_hal::wifi_radio_combination_matrix* legacy_matrix, + WifiRadioCombinationMatrix* hidl_matrix) { + if (!hidl_matrix || !legacy_matrix) { + return false; + } + *hidl_matrix = {}; + + int num_combinations = legacy_matrix->num_radio_combinations; + std::vector radio_combinations_vec; + if (!num_combinations) { + LOG(ERROR) << "zero radio combinations"; + return false; + } + wifi_radio_combination* l_radio_combinations_ptr = legacy_matrix->radio_combinations; + for (int i = 0; i < num_combinations; i++) { + int num_configurations = l_radio_combinations_ptr->num_radio_configurations; + WifiRadioCombination radioCombination; + std::vector radio_configurations_vec; + if (!num_configurations) { + LOG(ERROR) << "zero radio configurations"; + return false; + } + for (int j = 0; j < num_configurations; j++) { + WifiRadioConfiguration radioConfiguration; + wifi_radio_configuration* l_radio_configurations_ptr = + &l_radio_combinations_ptr->radio_configurations[j]; + if (!hidl_struct_util::convertLegacyWifiRadioConfigurationToHidl( + l_radio_configurations_ptr, &radioConfiguration)) { + LOG(ERROR) << "Error converting wifi radio configuration"; + return false; + } + radio_configurations_vec.push_back(radioConfiguration); + } + radioCombination.radioConfigurations = radio_configurations_vec; + radio_combinations_vec.push_back(radioCombination); + l_radio_combinations_ptr = + (wifi_radio_combination*)((u8*)l_radio_combinations_ptr + + sizeof(wifi_radio_combination) + + (sizeof(wifi_radio_configuration) * num_configurations)); + } + hidl_matrix->radioCombinations = radio_combinations_vec; + return true; +} + } // namespace hidl_struct_util } // namespace implementation } // namespace V1_6 diff --git a/wifi/1.6/default/hidl_struct_util.h b/wifi/1.6/default/hidl_struct_util.h index 26a6ebc85e..2d4a5f13f4 100644 --- a/wifi/1.6/default/hidl_struct_util.h +++ b/wifi/1.6/default/hidl_struct_util.h @@ -74,6 +74,11 @@ bool convertHidlCoexUnsafeChannelToLegacy( bool convertHidlVectorOfCoexUnsafeChannelToLegacy( const std::vector& hidl_unsafe_channels, std::vector* legacy_unsafe_channels); +bool convertLegacyRadioCombinationsMatrixToHidl( + legacy_hal::wifi_radio_combination_matrix* legacy_matrix, + V1_6::WifiRadioCombinationMatrix* hidl_matrix); +V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band); +V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg); // STA iface conversion methods. bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set, diff --git a/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp index 077c6cc8cd..0dd0aa15bb 100644 --- a/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp +++ b/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp @@ -377,6 +377,108 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyFeaturesToHidl) { HidlChipCaps::SET_LATENCY_MODE | HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP, hidle_caps); } + +void insertRadioCombination(legacy_hal::wifi_radio_combination* dst_radio_combination_ptr, + int num_radio_configurations, + legacy_hal::wifi_radio_configuration* radio_configuration) { + dst_radio_combination_ptr->num_radio_configurations = num_radio_configurations; + memcpy(dst_radio_combination_ptr->radio_configurations, radio_configuration, + num_radio_configurations * sizeof(legacy_hal::wifi_radio_configuration)); +} + +void verifyRadioCombination(WifiRadioCombination* radioCombination, size_t num_radio_configurations, + legacy_hal::wifi_radio_configuration* radio_configuration) { + EXPECT_EQ(num_radio_configurations, radioCombination->radioConfigurations.size()); + for (size_t i = 0; i < num_radio_configurations; i++) { + EXPECT_EQ(hidl_struct_util::convertLegacyMacBandToHidlWifiBand(radio_configuration->band), + radioCombination->radioConfigurations[i].bandInfo); + EXPECT_EQ(hidl_struct_util::convertLegacyAntennaConfigurationToHidl( + radio_configuration->antenna_cfg), + radioCombination->radioConfigurations[i].antennaMode); + radio_configuration++; + } +} + +TEST_F(HidlStructUtilTest, canConvertLegacyRadioCombinationsMatrixToHidl) { + legacy_hal::wifi_radio_configuration radio_configurations_array1[] = { + {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_1X1}, + }; + legacy_hal::wifi_radio_configuration radio_configurations_array2[] = { + {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_2X2}, + {.band = legacy_hal::WLAN_MAC_5_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_3X3}, + }; + legacy_hal::wifi_radio_configuration radio_configurations_array3[] = { + {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_2X2}, + {.band = legacy_hal::WLAN_MAC_6_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_1X1}, + {.band = legacy_hal::WLAN_MAC_5_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_4X4}, + }; + + int num_radio_configs = 0; + int num_combinations = 0; + std::array buffer; + buffer.fill(0); + legacy_hal::wifi_radio_combination_matrix* legacy_matrix = + reinterpret_cast(buffer.data()); + legacy_hal::wifi_radio_combination* radio_combinations; + + // Prepare a legacy wifi_radio_combination_matrix + legacy_matrix->num_radio_combinations = 3; + // Insert first combination + radio_combinations = + (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations); + insertRadioCombination( + radio_combinations, + sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]), + radio_configurations_array1); + num_combinations++; + num_radio_configs += + sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]); + + // Insert second combination + radio_combinations = + (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations + + (num_combinations * + sizeof(legacy_hal::wifi_radio_combination)) + + (num_radio_configs * + sizeof(wifi_radio_configuration))); + insertRadioCombination( + radio_combinations, + sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]), + radio_configurations_array2); + num_combinations++; + num_radio_configs += + sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]); + + // Insert third combination + radio_combinations = + (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations + + (num_combinations * + sizeof(legacy_hal::wifi_radio_combination)) + + (num_radio_configs * + sizeof(wifi_radio_configuration))); + insertRadioCombination( + radio_combinations, + sizeof(radio_configurations_array3) / sizeof(radio_configurations_array3[0]), + radio_configurations_array3); + + V1_6::WifiRadioCombinationMatrix converted_matrix{}; + hidl_struct_util::convertLegacyRadioCombinationsMatrixToHidl(legacy_matrix, &converted_matrix); + + // Verify the conversion + EXPECT_EQ(legacy_matrix->num_radio_combinations, converted_matrix.radioCombinations.size()); + verifyRadioCombination( + &converted_matrix.radioCombinations[0], + sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]), + radio_configurations_array1); + verifyRadioCombination( + &converted_matrix.radioCombinations[1], + sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]), + radio_configurations_array2); + verifyRadioCombination( + &converted_matrix.radioCombinations[2], + sizeof(radio_configurations_array3) / sizeof(radio_configurations_array3[0]), + radio_configurations_array3); +} } // namespace implementation } // namespace V1_6 } // namespace wifi diff --git a/wifi/1.6/default/wifi_chip.cpp b/wifi/1.6/default/wifi_chip.cpp index a1857246a7..4fff770dd2 100644 --- a/wifi/1.6/default/wifi_chip.cpp +++ b/wifi/1.6/default/wifi_chip.cpp @@ -722,6 +722,12 @@ Return WifiChip::getUsableChannels_1_6( filterMask); } +Return WifiChip::getSupportedRadioCombinationsMatrix( + getSupportedRadioCombinationsMatrix_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getSupportedRadioCombinationsMatrixInternal, hidl_status_cb); +} + void WifiChip::invalidateAndRemoveAllIfaces() { invalidateAndClearBridgedApAll(); invalidateAndClearAll(ap_ifaces_); @@ -1461,6 +1467,28 @@ std::pair> WifiChip::getUsableC return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels}; } +std::pair +WifiChip::getSupportedRadioCombinationsMatrixInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_radio_combination_matrix* legacy_matrix; + + std::tie(legacy_status, legacy_matrix) = + legacy_hal_.lock()->getSupportedRadioCombinationsMatrix(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + + V1_6::WifiRadioCombinationMatrix hidl_matrix; + if (!hidl_struct_util::convertLegacyRadioCombinationsMatrixToHidl(legacy_matrix, + &hidl_matrix)) { + LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToHidl() "; + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_matrix}; +} + WifiStatus WifiChip::handleChipConfiguration( /* NONNULL */ std::unique_lock* lock, ChipModeId mode_id) { // If the chip is already configured in a different mode, stop diff --git a/wifi/1.6/default/wifi_chip.h b/wifi/1.6/default/wifi_chip.h index 61ac03da83..13d62fb8dc 100644 --- a/wifi/1.6/default/wifi_chip.h +++ b/wifi/1.6/default/wifi_chip.h @@ -160,6 +160,8 @@ class WifiChip : public V1_6::IWifiChip { hidl_bitfield ifaceModeMask, hidl_bitfield filterMask, getUsableChannels_1_6_cb _hidl_cb) override; + Return getSupportedRadioCombinationsMatrix( + getSupportedRadioCombinationsMatrix_cb hidl_status_cb) override; private: void invalidateAndRemoveAllIfaces(); @@ -267,6 +269,7 @@ class WifiChip : public V1_6::IWifiChip { const sp& bound_iface); std::pair> getUsableChannelsInternal_1_6( WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask); + std::pair getSupportedRadioCombinationsMatrixInternal(); ChipId chip_id_; std::weak_ptr legacy_hal_; diff --git a/wifi/1.6/default/wifi_legacy_hal.cpp b/wifi/1.6/default/wifi_legacy_hal.cpp index 64dde9576e..b006e4596e 100644 --- a/wifi/1.6/default/wifi_legacy_hal.cpp +++ b/wifi/1.6/default/wifi_legacy_hal.cpp @@ -37,6 +37,7 @@ static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128; static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32; static constexpr uint32_t kMaxRingBuffers = 10; static constexpr uint32_t kMaxWifiUsableChannels = 256; +static constexpr uint32_t kMaxSupportedRadioCombinationsMatrixLength = 256; // need a long timeout (1000ms) for chips that unload their driver. static constexpr uint32_t kMaxStopCompleteWaitMs = 1000; static constexpr char kDriverPropName[] = "wlan.driver.status"; @@ -1537,6 +1538,19 @@ wifi_error WifiLegacyHal::setIndoorState(bool isIndoor) { return global_func_table_.wifi_set_indoor_state(global_handle_, isIndoor); } +std::pair +WifiLegacyHal::getSupportedRadioCombinationsMatrix() { + std::array buffer; + buffer.fill(0); + uint32_t size = 0; + wifi_radio_combination_matrix* radio_combination_matrix_ptr = + reinterpret_cast(buffer.data()); + wifi_error status = global_func_table_.wifi_get_supported_radio_combinations_matrix( + global_handle_, buffer.size(), &size, radio_combination_matrix_ptr); + CHECK(size >= 0 && size <= kMaxSupportedRadioCombinationsMatrixLength); + return {status, radio_combination_matrix_ptr}; +} + void WifiLegacyHal::invalidate() { global_handle_ = nullptr; iface_name_to_handle_.clear(); diff --git a/wifi/1.6/default/wifi_legacy_hal.h b/wifi/1.6/default/wifi_legacy_hal.h index 1d85d2e0b1..638bfa1598 100644 --- a/wifi/1.6/default/wifi_legacy_hal.h +++ b/wifi/1.6/default/wifi_legacy_hal.h @@ -204,6 +204,11 @@ using ::WIFI_AC_BE; using ::WIFI_AC_BK; using ::WIFI_AC_VI; using ::WIFI_AC_VO; +using ::WIFI_ANTENNA_1X1; +using ::WIFI_ANTENNA_2X2; +using ::WIFI_ANTENNA_3X3; +using ::WIFI_ANTENNA_4X4; +using ::WIFI_ANTENNA_UNSPECIFIED; using ::wifi_band; using ::WIFI_BAND_A; using ::WIFI_BAND_A_DFS; @@ -281,6 +286,9 @@ using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON; using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF; using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON; using ::WIFI_POWER_SCENARIO_VOICE_CALL; +using ::wifi_radio_combination; +using ::wifi_radio_combination_matrix; +using ::wifi_radio_configuration; using ::wifi_rate; using ::wifi_request_id; using ::wifi_ring_buffer_status; @@ -660,6 +668,8 @@ class WifiLegacyHal { wifi_error setIndoorState(bool isIndoor); + std::pair getSupportedRadioCombinationsMatrix(); + private: // Retrieve interface handles for all the available interfaces. wifi_error retrieveIfaceHandles(); diff --git a/wifi/1.6/default/wifi_legacy_hal_stubs.cpp b/wifi/1.6/default/wifi_legacy_hal_stubs.cpp index 7e66fab863..05a27cf33e 100644 --- a/wifi/1.6/default/wifi_legacy_hal_stubs.cpp +++ b/wifi/1.6/default/wifi_legacy_hal_stubs.cpp @@ -162,6 +162,7 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { populateStubFor(&hal_fn->wifi_get_usable_channels); populateStubFor(&hal_fn->wifi_trigger_subsystem_restart); populateStubFor(&hal_fn->wifi_set_indoor_state); + populateStubFor(&hal_fn->wifi_get_supported_radio_combinations_matrix); return true; } } // namespace legacy_hal diff --git a/wifi/1.6/types.hal b/wifi/1.6/types.hal index ef6965d4cf..80fdbd1541 100644 --- a/wifi/1.6/types.hal +++ b/wifi/1.6/types.hal @@ -46,6 +46,7 @@ import @1.0::WifiRateNss; import @1.4::RttPreamble; import @1.4::WifiRatePreamble; import @1.5::NanConfigRequestSupplemental; +import @1.5::WifiBand; import @1.5::StaLinkLayerIfaceContentionTimeStats; import @1.5::WifiIfaceMode; @@ -86,6 +87,17 @@ enum WifiRatePreamble : @1.4::WifiRatePreamble { EHT = 6, }; +/** + * Antenna configuration + */ +enum WifiAntennaMode : uint32_t { + WIFI_ANTENNA_MODE_UNSPECIFIED = 0, + WIFI_ANTENNA_MODE_1X1 = 1, + WIFI_ANTENNA_MODE_2X2 = 2, + WIFI_ANTENNA_MODE_3X3 = 3, + WIFI_ANTENNA_MODE_4X4 = 4, +}; + /** * Channel information. */ @@ -1262,3 +1274,41 @@ struct NanCapabilities { */ bool instantCommunicationModeSupportFlag; }; + +/** + * Wifi radio configuration + */ +struct WifiRadioConfiguration { + /** + * Band on which this radio chain is operating. + * Valid values of bandInfo are: BAND_24GHZ, BAND_5GHZ, BAND_6GHZ and + * BAND_60GHZ. + * + */ + WifiBand bandInfo; + + /** + * Wifi Antenna configuration. + */ + WifiAntennaMode antennaMode; +}; + +/** + * Wifi radio combination + */ +struct WifiRadioCombination { + /** + * A list of radio configurations in this combination. + */ + vec radioConfigurations; +}; + +/** + * Wifi radio combinations matrix retrieved via |getSupportedRadioCombinationsMatrix|. + */ +struct WifiRadioCombinationMatrix { + /** + * A list of all the possible radio combinations that the chip can operate. + */ + vec radioCombinations; +};