Merge "wifi: Get the supported radio combinations matrix"
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;
+};