wifi: Get the supported radio combinations matrix

Added API to get the supported radio combinations
of the chip. This is mainly to check if the chip is
capable of multi band simultaneous operation.

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

Bug: 208877624
Test: vts test
Change-Id: I4c90f80002ca138133a575bca80dfdef2a593ab2
diff --git a/wifi/1.6/IWifiChip.hal b/wifi/1.6/IWifiChip.hal
index eaa2400..555ec91 100644
--- a/wifi/1.6/IWifiChip.hal
+++ b/wifi/1.6/IWifiChip.hal
@@ -99,4 +99,35 @@
     getUsableChannels_1_6(WifiBand band, bitfield<WifiIfaceMode> ifaceModeMask,
         bitfield<UsableChannelFilter> filterMask)
         generates (WifiStatus status, vec<WifiUsableChannel> 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 71f98b9..45459e2 100644
--- a/wifi/1.6/default/hidl_struct_util.cpp
+++ b/wifi/1.6/default/hidl_struct_util.cpp
@@ -367,6 +367,21 @@
     }
 }
 
+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 @@
     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<V1_6::WifiRadioCombination> 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<V1_6::WifiRadioConfiguration> 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 26a6ebc..2d4a5f1 100644
--- a/wifi/1.6/default/hidl_struct_util.h
+++ b/wifi/1.6/default/hidl_struct_util.h
@@ -74,6 +74,11 @@
 bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
         const std::vector<V1_5::IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
         std::vector<legacy_hal::wifi_coex_unsafe_channel>* 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 077c6cc..0dd0aa1 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 @@
                       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<char, 256> buffer;
+    buffer.fill(0);
+    legacy_hal::wifi_radio_combination_matrix* legacy_matrix =
+            reinterpret_cast<wifi_radio_combination_matrix*>(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 a185724..4fff770 100644
--- a/wifi/1.6/default/wifi_chip.cpp
+++ b/wifi/1.6/default/wifi_chip.cpp
@@ -722,6 +722,12 @@
                            filterMask);
 }
 
+Return<void> 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 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels};
 }
 
+std::pair<WifiStatus, V1_6::WifiRadioCombinationMatrix>
+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<std::recursive_mutex>* 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 61ac03d..13d62fb 100644
--- a/wifi/1.6/default/wifi_chip.h
+++ b/wifi/1.6/default/wifi_chip.h
@@ -160,6 +160,8 @@
                                        hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask,
                                        hidl_bitfield<UsableChannelFilter> filterMask,
                                        getUsableChannels_1_6_cb _hidl_cb) override;
+    Return<void> getSupportedRadioCombinationsMatrix(
+            getSupportedRadioCombinationsMatrix_cb hidl_status_cb) override;
 
   private:
     void invalidateAndRemoveAllIfaces();
@@ -267,6 +269,7 @@
             const sp<IWifiIface>& bound_iface);
     std::pair<WifiStatus, std::vector<V1_6::WifiUsableChannel>> getUsableChannelsInternal_1_6(
             WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask);
+    std::pair<WifiStatus, WifiRadioCombinationMatrix> getSupportedRadioCombinationsMatrixInternal();
 
     ChipId chip_id_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
diff --git a/wifi/1.6/default/wifi_legacy_hal.cpp b/wifi/1.6/default/wifi_legacy_hal.cpp
index 64dde95..b006e45 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 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 @@
     return global_func_table_.wifi_set_indoor_state(global_handle_, isIndoor);
 }
 
+std::pair<wifi_error, wifi_radio_combination_matrix*>
+WifiLegacyHal::getSupportedRadioCombinationsMatrix() {
+    std::array<char, kMaxSupportedRadioCombinationsMatrixLength> buffer;
+    buffer.fill(0);
+    uint32_t size = 0;
+    wifi_radio_combination_matrix* radio_combination_matrix_ptr =
+            reinterpret_cast<wifi_radio_combination_matrix*>(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 1d85d2e..638bfa1 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_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_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 @@
 
     wifi_error setIndoorState(bool isIndoor);
 
+    std::pair<wifi_error, wifi_radio_combination_matrix*> 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 7e66fab..05a27cf 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 @@
     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 ef6965d..80fdbd1 100644
--- a/wifi/1.6/types.hal
+++ b/wifi/1.6/types.hal
@@ -46,6 +46,7 @@
 import @1.4::RttPreamble;
 import @1.4::WifiRatePreamble;
 import @1.5::NanConfigRequestSupplemental;
+import @1.5::WifiBand;
 import @1.5::StaLinkLayerIfaceContentionTimeStats;
 import @1.5::WifiIfaceMode;
 
@@ -87,6 +88,17 @@
 };
 
 /**
+ * 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.
  */
 struct WifiChannelInfo {
@@ -1262,3 +1274,41 @@
      */
     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<WifiRadioConfiguration> radioConfigurations;
+};
+
+/**
+ * Wifi radio combinations matrix retrieved via |getSupportedRadioCombinationsMatrix|.
+ */
+struct WifiRadioCombinationMatrix {
+    /**
+     * A list of all the possible radio combinations that the chip can operate.
+     */
+    vec<WifiRadioCombination> radioCombinations;
+};