diff --git a/include/webconfig_external_proto_easymesh.h b/include/webconfig_external_proto_easymesh.h index 433fa8c48..2274c0150 100644 --- a/include/webconfig_external_proto_easymesh.h +++ b/include/webconfig_external_proto_easymesh.h @@ -47,6 +47,7 @@ typedef void (*ext_proto_update_ap_mld_info_t)(void *data_model, em_ap_mld_info_ typedef void (*ext_proto_update_bsta_mld_info_t)(void *data_model, em_bsta_mld_info_t *bsta_mld_info); typedef void (*ext_proto_update_assoc_sta_mld_info_t)(void *data_model, em_assoc_sta_mld_info_t *assoc_sta_mld_info); typedef em_ap_mld_info_t * (*ext_proto_get_ap_mld_frm_bssid_t)(void *data_model, mac_address_t bss_id); +typedef void * (*ext_proto_get_radio_cap_t)(void *data_model, mac_address_t ruid); typedef struct { void *data_model; /* agent data model dm_easy_mesh_t */ @@ -75,7 +76,8 @@ typedef struct { ext_proto_update_ap_mld_info_t update_ap_mld_info; ext_proto_update_bsta_mld_info_t update_bsta_mld_info; ext_proto_update_assoc_sta_mld_info_t update_assoc_sta_mld_info; - ext_proto_get_ap_mld_frm_bssid_t get_ap_mld_frm_bssid; + ext_proto_get_ap_mld_frm_bssid_t get_ap_mld_frm_bssid; + ext_proto_get_radio_cap_t get_radio_cap; } webconfig_external_easymesh_t; void webconfig_proto_easymesh_init(webconfig_external_easymesh_t *proto, void *data_model, void *m2ctrl_vapconfig, void *policy_config, @@ -89,7 +91,7 @@ void webconfig_proto_easymesh_init(webconfig_external_easymesh_t *proto, void *d ext_proto_get_sta_info_t get_sta, ext_proto_put_sta_info_t put_sta, ext_proto_em_get_bss_info_with_mac_t get_bss_info_with_mac, ext_proto_put_scan_results_t put_scan_results, ext_proto_update_ap_mld_info_t update_ap_mld_info, ext_proto_update_bsta_mld_info_t update_bsta_mld_info, ext_proto_update_assoc_sta_mld_info_t update_assoc_sta_mld_info, - ext_proto_get_ap_mld_frm_bssid_t get_ap_mld_frm_bssid); + ext_proto_get_ap_mld_frm_bssid_t get_ap_mld_frm_bssid, ext_proto_get_radio_cap_t get_radio_cap); #ifdef __cplusplus } diff --git a/include/wifi_base.h b/include/wifi_base.h index 274c30259..95784c0a2 100644 --- a/include/wifi_base.h +++ b/include/wifi_base.h @@ -842,12 +842,38 @@ typedef struct { int ap_reason_counts[9]; } interop_data_t; +typedef struct { + /* WiFi6 (HE) capabilities */ + BOOL wifi6_supported; /**< Whether WiFi6 (HE) is supported */ + UCHAR phy_cap[11]; /**< HE PHY capabilities (HE_MAX_PHY_CAPAB_SIZE = 11) */ + UCHAR mac_cap[4]; /**< HE MAC capabilities (HE_MAX_MAC_CAPAB_SIZE = 4) */ + UCHAR mcs_nss_set[6]; /**< HE MCS NSS set (HE_MAX_MCS_CAPAB_SIZE = 6) */ + UCHAR ppet[7]; /**< HE PPE thresholds (HE_MAX_PPET_CAPAB_SIZE = 7) */ + //USHORT 6ghz_capa; /**< HE 6GHz capabilities */ +} he_radio_capability_t; + +typedef struct { + /* WiFi7 (EHT) capabilities */ + BOOL wifi7_supported; /**< Whether WiFi7 (EHT) is supported */ + UCHAR mac_cap[4]; /**< EHT MAC capabilities */ + UCHAR phy_cap[9]; /**< EHT PHY capabilities (EHT_PHY_CAPAB_LEN = 9) */ + UCHAR mcs[3]; /**< EHT MCS set */ + UCHAR ppet[16]; /**< EHT PPE thresholds */ +} eht_radio_capability_t; + +/* This structure is populated from HAL and translated to easymesh */ +typedef struct { + he_radio_capability_t he_cap; + eht_radio_capability_t eht_cap; +} __attribute__((packed)) rdk_wifi_radio_capability_t; + typedef struct { char name[16]; wifi_radio_operationParam_t oper; rdk_wifi_vap_map_t vaps; wifi_radio_feature_param_t feature; radarInfo_t radarInfo; + rdk_wifi_radio_capability_t radio_capability; /**< WiFi6/WiFi7 capabilities for AP mode */ // schema_wifi_radio_state_t radio_state; } rdk_wifi_radio_t; diff --git a/source/core/wifi_mgr.c b/source/core/wifi_mgr.c index 86bf1d5d9..95e35d699 100644 --- a/source/core/wifi_mgr.c +++ b/source/core/wifi_mgr.c @@ -117,9 +117,47 @@ int init_wifi_hal() wifi_util_error_print(WIFI_CTRL,"RDK_LOG_ERROR, %s wifi_getHalCapability returned with error %d\n", __FUNCTION__, ret); return RETURN_ERR; } + + wifi_util_info_print(WIFI_CTRL,"%s:%d: Calling wifi_hal_print_all_he_eht_capabilities\n", __func__, __LINE__); + //wifi_hal_print_all_he_eht_capabilities(); + wifi_util_info_print(WIFI_CTRL,"%s:%d: after wifi_hal_print_all_he_eht_capabilities\n", __func__, __LINE__); + return RETURN_OK; } +void dump_hw_caps(rdk_wifi_radio_t *radios_cfg) +{ + wifi_util_info_print(WIFI_CTRL,"%s:%d:Inside\n", __func__, __LINE__); + if (radios_cfg->radio_capability.he_cap.wifi6_supported) { + wifi_util_info_print(WIFI_CTRL,"%s:%d: HE Supported: YES\n", __func__, __LINE__); + wifi_util_info_print(WIFI_CTRL,"%s:%d: HE PHY Cap: ", __func__, __LINE__); + wifi_util_info_print(WIFI_CTRL,"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + radios_cfg->radio_capability.he_cap.phy_cap[0], radios_cfg->radio_capability.he_cap.phy_cap[1], + radios_cfg->radio_capability.he_cap.phy_cap[2], radios_cfg->radio_capability.he_cap.phy_cap[3], + radios_cfg->radio_capability.he_cap.phy_cap[4], radios_cfg->radio_capability.he_cap.phy_cap[5], + radios_cfg->radio_capability.he_cap.phy_cap[6], radios_cfg->radio_capability.he_cap.phy_cap[7], + radios_cfg->radio_capability.he_cap.phy_cap[8], radios_cfg->radio_capability.he_cap.phy_cap[9], + radios_cfg->radio_capability.he_cap.phy_cap[10]); + wifi_util_info_print(WIFI_CTRL,"\n"); + //wifi_util_info_print(WIFI_CTRL,"%s:%d: HE MAC Cap: ", __func__, __LINE__); + //wifi_util_info_print(WIFI_CTRL,"%02x:%02x:%02x:%02x", + // radios_cfg->radio_capability.he_cap.mac_cap[0], radios_cfg->radio_capability.he_cap.mac_cap[1], + // radios_cfg->radio_capability.he_cap.mac_cap[2], radios_cfg->radio_capability.he_cap.mac_cap[3]); + //wifi_util_info_print(WIFI_CTRL,"\n"); + //wifi_util_info_print(WIFI_CTRL,"%s:%d: HE MCS: ", __func__, __LINE__); + //wifi_util_info_print(WIFI_CTRL,"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x: \ + // %02x:%02x:", radios_cfg->radio_capability.he_cap.mcs[0], radios_cfg->radio_capability.he_cap.mcs[1], + // radios_cfg->radio_capability.he_cap.mcs[2], radios_cfg->radio_capability.he_cap.mcs[3], + // radios_cfg->radio_capability.he_cap.mcs[4], radios_cfg->radio_capability.he_cap.mcs[5], + // radios_cfg->radio_capability.he_cap.mcs[6], radios_cfg->radio_capability.he_cap.mcs[7], + // radios_cfg->radio_capability.he_cap.mcs[8], radios_cfg->radio_capability.he_cap.mcs[9], + // radios_cfg->radio_capability.he_cap.mcs[10], radios_cfg->radio_capability.he_cap.mcs[11]); + //wifi_util_info_print(WIFI_CTRL,"\n"); + } else { + wifi_util_info_print(WIFI_CTRL,"%s:%d: HE Supported: NO\n", __func__, __LINE__); + } +} + int init_global_radio_config(rdk_wifi_radio_t *radios_cfg, UINT radio_index) { UINT vap_array_index = 0; @@ -174,6 +212,38 @@ int init_global_radio_config(rdk_wifi_radio_t *radios_cfg, UINT radio_index) radios_cfg->vaps.radio_index = radio_index; radios_cfg->vaps.num_vaps = vap_array_index; radios_cfg->vaps.vap_map.num_vaps = vap_array_index; + + /* Populate radio capabilities from HAL */ + wifi_freq_bands_t band; + if (convert_radio_index_to_freq_band(&wifi_hal_cap_obj->wifi_prop, radio_index, &band) == RETURN_OK) { + wifi_radio_capability_data_t *hal_cap_data = (wifi_radio_capability_data_t *)malloc(sizeof(wifi_radio_capability_data_t)); + memset(&hal_cap_data, 0, sizeof(hal_cap_data)); + + if (wifi_getRadioCapabilityData(radio_index, band, hal_cap_data) == RETURN_OK) { + /* Copy from HAL structure to OneWifi structure */ + radios_cfg->radio_capability.he_cap.wifi6_supported = hal_cap_data->wifi6_supported; + memcpy(radios_cfg->radio_capability.he_cap.phy_cap, hal_cap_data->he_phy_cap, sizeof(hal_cap_data->he_phy_cap)); + memcpy(radios_cfg->radio_capability.he_cap.mac_cap, hal_cap_data->he_mac_cap, sizeof(hal_cap_data->he_mac_cap)); + memcpy(radios_cfg->radio_capability.he_cap.mcs_nss_set, hal_cap_data->he_mcs_nss_set, sizeof(hal_cap_data->he_mcs_nss_set)); + memcpy(radios_cfg->radio_capability.he_cap.ppet, hal_cap_data->he_ppet, sizeof(hal_cap_data->he_ppet)); + + radios_cfg->radio_capability.eht_cap.wifi7_supported = hal_cap_data->wifi7_supported; + memcpy(radios_cfg->radio_capability.eht_cap.mac_cap, hal_cap_data->eht_mac_cap, sizeof(hal_cap_data->eht_mac_cap)); + memcpy(radios_cfg->radio_capability.eht_cap.phy_cap, hal_cap_data->eht_phy_cap, sizeof(hal_cap_data->eht_phy_cap)); + memcpy(radios_cfg->radio_capability.eht_cap.mcs, hal_cap_data->eht_mcs, sizeof(hal_cap_data->eht_mcs)); + memcpy(radios_cfg->radio_capability.eht_cap.ppet, hal_cap_data->eht_ppet, sizeof(hal_cap_data->eht_ppet)); + } else { + wifi_util_dbg_print(WIFI_CTRL, "%s:%d: Failed to get radio capability data for radio %d\n", + __func__, __LINE__, radio_index); + } + } else { + wifi_util_dbg_print(WIFI_CTRL, "%s:%d: Failed to convert radio index %d to band\n", + __func__, __LINE__, radio_index); + } + + wifi_util_dbg_print(WIFI_CTRL, "%s:%d:Calling dump_hw_caps\n", __func__, __LINE__); + dump_hw_caps(radios_cfg); + return RETURN_OK; } diff --git a/source/webconfig/wifi_decoder.c b/source/webconfig/wifi_decoder.c index 9d34610d8..fadbfcb0d 100644 --- a/source/webconfig/wifi_decoder.c +++ b/source/webconfig/wifi_decoder.c @@ -2904,6 +2904,160 @@ webconfig_error_t decode_radio_curr_operating_classes(const cJSON *obj_radio_set return webconfig_error_none; } +/* Decode radio capabilities (WiFi6/WiFi7) from JSON */ +webconfig_error_t decode_radio_capability(const cJSON *cap_obj, rdk_wifi_radio_capability_t *radio_cap) +{ +#if 0 + const cJSON *param; + cJSON *array_item; + int i, array_size; + + if (cap_obj == NULL || radio_cap == NULL) { + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d NULL pointer\n", __func__, __LINE__); + return webconfig_error_decode; + } + + memset(radio_cap, 0, sizeof(rdk_wifi_radio_capability_t)); + + /* WiFi6 (HE) capabilities */ +#ifdef CONFIG_IEEE80211AX + decode_param_bool(cap_obj, "WiFi6Supported", param); + if (param != NULL) { + radio_cap->wifi6_supported = (param->type & cJSON_True) ? true : false; + } + + param = cJSON_GetObjectItem(cap_obj, "HEPHYCap"); + if (param != NULL && cJSON_IsArray(param)) { + array_size = cJSON_GetArraySize(param); + if (array_size > sizeof(radio_cap->he_phy_cap)) { + array_size = sizeof(radio_cap->he_phy_cap); + } + for (i = 0; i < array_size; i++) { + array_item = cJSON_GetArrayItem(param, i); + if (cJSON_IsNumber(array_item)) { + radio_cap->he_phy_cap[i] = (UCHAR)array_item->valuedouble; + } + } + } + + param = cJSON_GetObjectItem(cap_obj, "HEMACCap"); + if (param != NULL && cJSON_IsArray(param)) { + array_size = cJSON_GetArraySize(param); + if (array_size > sizeof(radio_cap->he_mac_cap)) { + array_size = sizeof(radio_cap->he_mac_cap); + } + for (i = 0; i < array_size; i++) { + array_item = cJSON_GetArrayItem(param, i); + if (cJSON_IsNumber(array_item)) { + radio_cap->he_mac_cap[i] = (UCHAR)array_item->valuedouble; + } + } + } + + param = cJSON_GetObjectItem(cap_obj, "HEMCSNSSSet"); + if (param != NULL && cJSON_IsArray(param)) { + array_size = cJSON_GetArraySize(param); + if (array_size > sizeof(radio_cap->he_mcs_nss_set)) { + array_size = sizeof(radio_cap->he_mcs_nss_set); + } + for (i = 0; i < array_size; i++) { + array_item = cJSON_GetArrayItem(param, i); + if (cJSON_IsNumber(array_item)) { + radio_cap->he_mcs_nss_set[i] = (UCHAR)array_item->valuedouble; + } + } + } + + param = cJSON_GetObjectItem(cap_obj, "HEPPET"); + if (param != NULL && cJSON_IsArray(param)) { + array_size = cJSON_GetArraySize(param); + if (array_size > sizeof(radio_cap->he_ppet)) { + array_size = sizeof(radio_cap->he_ppet); + } + for (i = 0; i < array_size; i++) { + array_item = cJSON_GetArrayItem(param, i); + if (cJSON_IsNumber(array_item)) { + radio_cap->he_ppet[i] = (UCHAR)array_item->valuedouble; + } + } + } + + decode_param_integer(cap_obj, "HE6GHzCapa", param); + if (param != NULL && cJSON_IsNumber(param)) { + radio_cap->he_6ghz_capa = (USHORT)param->valuedouble; + } +#endif /* CONFIG_IEEE80211AX */ + + /* WiFi7 (EHT) capabilities */ +#ifdef CONFIG_IEEE80211BE +#if HOSTAPD_VERSION >= 211 + decode_param_bool(cap_obj, "WiFi7Supported", param); + if (param != NULL) { + radio_cap->wifi7_supported = (param->type & cJSON_True) ? true : false; + } + + param = cJSON_GetObjectItem(cap_obj, "EHTMACCap"); + if (param != NULL && cJSON_IsArray(param)) { + array_size = cJSON_GetArraySize(param); + if (array_size > sizeof(radio_cap->eht_mac_cap)) { + array_size = sizeof(radio_cap->eht_mac_cap); + } + for (i = 0; i < array_size; i++) { + array_item = cJSON_GetArrayItem(param, i); + if (cJSON_IsNumber(array_item)) { + radio_cap->eht_mac_cap[i] = (UCHAR)array_item->valuedouble; + } + } + } + + param = cJSON_GetObjectItem(cap_obj, "EHTPHYCap"); + if (param != NULL && cJSON_IsArray(param)) { + array_size = cJSON_GetArraySize(param); + if (array_size > sizeof(radio_cap->eht_phy_cap)) { + array_size = sizeof(radio_cap->eht_phy_cap); + } + for (i = 0; i < array_size; i++) { + array_item = cJSON_GetArrayItem(param, i); + if (cJSON_IsNumber(array_item)) { + radio_cap->eht_phy_cap[i] = (UCHAR)array_item->valuedouble; + } + } + } + + param = cJSON_GetObjectItem(cap_obj, "EHTMCS"); + if (param != NULL && cJSON_IsArray(param)) { + array_size = cJSON_GetArraySize(param); + if (array_size > sizeof(radio_cap->eht_mcs)) { + array_size = sizeof(radio_cap->eht_mcs); + } + for (i = 0; i < array_size; i++) { + array_item = cJSON_GetArrayItem(param, i); + if (cJSON_IsNumber(array_item)) { + radio_cap->eht_mcs[i] = (UCHAR)array_item->valuedouble; + } + } + } + + param = cJSON_GetObjectItem(cap_obj, "EHTPPET"); + if (param != NULL && cJSON_IsArray(param)) { + array_size = cJSON_GetArraySize(param); + if (array_size > sizeof(radio_cap->eht_ppet)) { + array_size = sizeof(radio_cap->eht_ppet); + } + for (i = 0; i < array_size; i++) { + array_item = cJSON_GetArrayItem(param, i); + if (cJSON_IsNumber(array_item)) { + radio_cap->eht_ppet[i] = (UCHAR)array_item->valuedouble; + } + } + } +#endif /* HOSTAPD_VERSION >= 211 */ +#endif /* CONFIG_IEEE80211BE */ +#endif + + return webconfig_error_none; +} + webconfig_error_t decode_radio_object(const cJSON *obj_radio, rdk_wifi_radio_t *radio) { const cJSON *param; @@ -3249,6 +3403,16 @@ webconfig_error_t decode_radio_object(const cJSON *obj_radio, rdk_wifi_radio_t * wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d Radio current operation class decoding failed\n", __func__, __LINE__); } + + // Radio Capabilities (WiFi6/WiFi7) + decode_param_object(obj_radio, "RadioCapability", param); + if (param != NULL) { + if (decode_radio_capability(param, &radio->radio_capability) != webconfig_error_none) { + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d Radio capability decode failed\n", __func__, __LINE__); + return webconfig_error_decode; + } + } + return webconfig_error_none; } diff --git a/source/webconfig/wifi_easymesh_translator.c b/source/webconfig/wifi_easymesh_translator.c index ebd5352ef..1de5bb0ac 100644 --- a/source/webconfig/wifi_easymesh_translator.c +++ b/source/webconfig/wifi_easymesh_translator.c @@ -274,6 +274,54 @@ webconfig_error_t translate_device_object_to_easymesh_for_dml(webconfig_subdoc return webconfig_error_none; } + +/* Helper function to translate radio capabilities from OneWifi to EasyMesh */ +static webconfig_error_t translate_radio_capability_to_easymesh( + const rdk_wifi_radio_capability_t *radio_cap, + mac_address_t ruid, + webconfig_external_easymesh_t *proto) +{ +#if 0 + void *radio_cap_ptr; + void *cap_info_ptr; + em_radio_wifi6_cap_data_t *wifi6_cap; + em_wifi7_agent_cap_t *wifi7_cap; + em_radio_wifi7_radio_t *wifi7_radio; + unsigned int i; + unsigned short mcs_nss_val; + + if (radio_cap == NULL || proto == NULL || proto->get_radio_cap == NULL) { + wifi_util_dbg_print(WIFI_WEBCONFIG, "%s:%d: NULL pointer or get_radio_cap not set\n", __func__, __LINE__); + return webconfig_error_translate_to_easymesh; + } + + /* Get radio capability from easymesh data model */ + radio_cap_ptr = proto->get_radio_cap(proto->data_model, ruid); + if (radio_cap_ptr == NULL) { + wifi_util_dbg_print(WIFI_WEBCONFIG, "%s:%d: Failed to get radio_cap for ruid\n", __func__, __LINE__); + return webconfig_error_translate_to_easymesh; + } + + /* WiFi6 (HE) capabilities translation */ +#ifdef CONFIG_IEEE80211AX + if (radio_cap->wifi6_supported) { + wifi_util_dbg_print(WIFI_WEBCONFIG, "%s:%d: WiFi6 supported, capability translation needed\n", __func__, __LINE__); + } +#endif /* CONFIG_IEEE80211AX */ + + /* WiFi7 (EHT) capabilities translation */ +#ifdef CONFIG_IEEE80211BE +#if HOSTAPD_VERSION >= 211 + if (radio_cap->wifi7_supported) { + wifi_util_dbg_print(WIFI_WEBCONFIG, "%s:%d: WiFi7 supported, capability translation needed\n", __func__, __LINE__); + } +#endif /* HOSTAPD_VERSION >= 211 */ +#endif /* CONFIG_IEEE80211BE */ +#endif + + return webconfig_error_none; +} + // This routine converts Radio webconfig subdoc values to em_radio_list_t,em_radio_info_t easymesh structures webconfig_error_t translate_radio_object_to_easymesh_for_radio(webconfig_subdoc_data_t *data) { @@ -2991,7 +3039,7 @@ void webconfig_proto_easymesh_init(webconfig_external_easymesh_t *proto, void *d ext_proto_get_sta_info_t get_sta, ext_proto_put_sta_info_t put_sta, ext_proto_em_get_bss_info_with_mac_t get_bss_with_mac, ext_proto_put_scan_results_t put_scan_res, ext_proto_update_ap_mld_info_t update_ap_mld, ext_proto_update_bsta_mld_info_t update_bsta_mld, ext_proto_update_assoc_sta_mld_info_t update_assoc_sta_mld, - ext_proto_get_ap_mld_frm_bssid_t get_ap_mld_frm_bssid) + ext_proto_get_ap_mld_frm_bssid_t get_ap_mld_frm_bssid, ext_proto_get_radio_cap_t get_radio_cap) { proto->data_model = data_model; proto->m2ctrl_radioconfig = m2ctrl_radioconfig; @@ -3018,4 +3066,5 @@ void webconfig_proto_easymesh_init(webconfig_external_easymesh_t *proto, void *d proto->update_bsta_mld_info = update_bsta_mld; proto->update_assoc_sta_mld_info = update_assoc_sta_mld; proto->get_ap_mld_frm_bssid = get_ap_mld_frm_bssid; + proto->get_radio_cap = get_radio_cap; } diff --git a/source/webconfig/wifi_encoder.c b/source/webconfig/wifi_encoder.c index 35a6868d2..5eb98f62d 100644 --- a/source/webconfig/wifi_encoder.c +++ b/source/webconfig/wifi_encoder.c @@ -107,6 +107,82 @@ webconfig_error_t encode_radio_curr_operating_classes(const wifi_radio_operation return webconfig_error_none; } +/* Encode radio capabilities (WiFi6/WiFi7) to JSON */ +webconfig_error_t encode_radio_capability(const rdk_wifi_radio_capability_t *radio_cap, cJSON *radio_object) +{ +#if 0 + cJSON *cap_obj; + + if (radio_cap == NULL || radio_object == NULL) { + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d NULL pointer\n", __func__, __LINE__); + return webconfig_error_encode; + } + + cap_obj = cJSON_CreateObject(); + if (cap_obj == NULL) { + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d Failed to create radio capability object\n", __func__, __LINE__); + return webconfig_error_encode; + } + cJSON_AddItemToObject(radio_object, "RadioCapability", cap_obj); + + /* WiFi6 (HE) capabilities */ +#ifdef CONFIG_IEEE80211AX + cJSON_AddBoolToObject(cap_obj, "WiFi6Supported", radio_cap->wifi6_supported); + + cJSON *he_phy_cap_array = cJSON_CreateIntArray((int *)radio_cap->he_phy_cap, sizeof(radio_cap->he_phy_cap)); + if (he_phy_cap_array != NULL) { + cJSON_AddItemToObject(cap_obj, "HEPHYCap", he_phy_cap_array); + } + + cJSON *he_mac_cap_array = cJSON_CreateIntArray((int *)radio_cap->he_mac_cap, sizeof(radio_cap->he_mac_cap)); + if (he_mac_cap_array != NULL) { + cJSON_AddItemToObject(cap_obj, "HEMACCap", he_mac_cap_array); + } + + cJSON *he_mcs_nss_array = cJSON_CreateIntArray((int *)radio_cap->he_mcs_nss_set, sizeof(radio_cap->he_mcs_nss_set)); + if (he_mcs_nss_array != NULL) { + cJSON_AddItemToObject(cap_obj, "HEMCSNSSSet", he_mcs_nss_array); + } + + cJSON *he_ppet_array = cJSON_CreateIntArray((int *)radio_cap->he_ppet, sizeof(radio_cap->he_ppet)); + if (he_ppet_array != NULL) { + cJSON_AddItemToObject(cap_obj, "HEPPET", he_ppet_array); + } + + cJSON_AddNumberToObject(cap_obj, "HE6GHzCapa", radio_cap->he_6ghz_capa); +#endif /* CONFIG_IEEE80211AX */ + + /* WiFi7 (EHT) capabilities */ +#ifdef CONFIG_IEEE80211BE +#if HOSTAPD_VERSION >= 211 + cJSON_AddBoolToObject(cap_obj, "WiFi7Supported", radio_cap->wifi7_supported); + + cJSON *eht_mac_cap_array = cJSON_CreateIntArray((int *)radio_cap->eht_mac_cap, sizeof(radio_cap->eht_mac_cap)); + if (eht_mac_cap_array != NULL) { + cJSON_AddItemToObject(cap_obj, "EHTMACCap", eht_mac_cap_array); + } + + cJSON *eht_phy_cap_array = cJSON_CreateIntArray((int *)radio_cap->eht_phy_cap, sizeof(radio_cap->eht_phy_cap)); + if (eht_phy_cap_array != NULL) { + cJSON_AddItemToObject(cap_obj, "EHTPHYCap", eht_phy_cap_array); + } + + cJSON *eht_mcs_array = cJSON_CreateIntArray((int *)radio_cap->eht_mcs, sizeof(radio_cap->eht_mcs)); + if (eht_mcs_array != NULL) { + cJSON_AddItemToObject(cap_obj, "EHTMCS", eht_mcs_array); + } + + cJSON *eht_ppet_array = cJSON_CreateIntArray((int *)radio_cap->eht_ppet, sizeof(radio_cap->eht_ppet)); + if (eht_ppet_array != NULL) { + cJSON_AddItemToObject(cap_obj, "EHTPPET", eht_ppet_array); + } +#endif /* HOSTAPD_VERSION >= 211 */ +#endif /* CONFIG_IEEE80211BE */ +#endif + + return webconfig_error_none; +} + webconfig_error_t encode_radio_object(const rdk_wifi_radio_t *radio, cJSON *radio_object) { const wifi_radio_operationParam_t *radio_info; @@ -361,6 +437,12 @@ webconfig_error_t encode_radio_object(const rdk_wifi_radio_t *radio, cJSON *radi "%s:%d Radio current operation class encoding failed\n", __func__, __LINE__); return webconfig_error_encode; } + + // Radio Capabilities (WiFi6/WiFi7) + if (encode_radio_capability(&radio->radio_capability, radio_object) != webconfig_error_none) { + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d Radio capability encoding failed\n", __func__, __LINE__); + return webconfig_error_encode; + } return webconfig_error_none; }