diff --git a/include/webconfig_external_proto_easymesh.h b/include/webconfig_external_proto_easymesh.h index 433fa8c48..b49d31ef7 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 em_radio_cap_info_t * (*ext_proto_get_radio_cap_t)(void *data_model, int index); 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 ccf9f2b9b..c0771e7c3 100644 --- a/include/wifi_base.h +++ b/include/wifi_base.h @@ -155,6 +155,19 @@ extern "C" { #define CFG_ID_LEN 64 typedef char stats_cfg_id_t[CFG_ID_LEN]; +/* HE PHY/MAC capability bit positions (IEEE 802.11ax-2021) */ +#define HE_PHY_CHAN_WIDTH_160_BIT 3 +#define HE_PHY_CHAN_WIDTH_80P80_BIT 4 +#define HE_PHY_SU_BEAMFORMER_BIT 7 /* byte 3 */ +#define HE_PHY_SU_BEAMFORMEE_BIT 0 /* byte 4 */ +#define HE_PHY_MU_BEAMFORMER_BIT 1 /* byte 4 */ +#define HE_MAC_TWT_REQ_BIT 0 /* byte 0 */ +#define HE_MAC_TWT_RESP_BIT 1 /* byte 0 */ +#define HE_MAC_DL_MU_MIMO_BIT 0 /* byte 4 */ +#define HE_MAC_UL_MU_MIMO_BIT 1 /* byte 4 */ +#define HE_MAC_UL_OFDMA_BIT 2 /* byte 2 */ +#define HE_MAC_DL_OFDMA_BIT 3 /* byte 2 */ + typedef enum { wifi_app_inst_blaster = wifi_app_inst_base, wifi_app_inst_harvester = wifi_app_inst_base << 1, diff --git a/source/webconfig/wifi_decoder.c b/source/webconfig/wifi_decoder.c index 156f3b547..9dfcaf050 100644 --- a/source/webconfig/wifi_decoder.c +++ b/source/webconfig/wifi_decoder.c @@ -4850,13 +4850,26 @@ webconfig_error_t decode_wifiradiocap(wifi_platform_property_t *wifi_prop, cJSON for (i = 0; i < size; i++) { object = cJSON_GetArrayItem(obj_wificap, i); radio_cap = &wifi_prop->radiocap[i]; + value_object = cJSON_GetObjectItem(object, "PhyIndex"); + if ((value_object == NULL) || (cJSON_IsNumber(value_object) == false)) { + /* Fallback to legacy RadioIndex for older producers */ + cJSON *legacy_radio_index = cJSON_GetObjectItem(object, "RadioIndex"); + if ((legacy_radio_index == NULL) || (cJSON_IsNumber(legacy_radio_index) == false)) { + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d: Validation Failed\n", __func__, __LINE__); + return webconfig_error_decode; + } + radio_cap->index = legacy_radio_index->valuedouble; + } else { + radio_cap->index = value_object->valuedouble; + } + value_object = cJSON_GetObjectItem(object, "RadioIndex"); if ((value_object == NULL) || (cJSON_IsNumber(value_object) == false)) { wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d: Validation Failed\n", __func__, __LINE__); return webconfig_error_decode; } - radio_cap->index = value_object->valuedouble; + radio_cap->rdk_radio_index = value_object->valuedouble; /*allowed_channels*/ allowed_channels = cJSON_GetObjectItem(object, "PossibleChannels"); @@ -4896,6 +4909,129 @@ webconfig_error_t decode_wifiradiocap(wifi_platform_property_t *wifi_prop, cJSON return webconfig_error_decode; } wifi_prop->radio_presence[i] = value_object->valuedouble; + +#ifdef CONFIG_IEEE80211AX + /* WiFi6 (HE) capabilities */ + decode_param_bool(object, "WiFi6Supported", value_object); + if (value_object != NULL) { + radio_cap->wifi6_supported = (value_object->type & cJSON_True) ? true : false; + } + + value_object = cJSON_GetObjectItem(object, "HEPHYCap"); + if (value_object != NULL && cJSON_IsArray(value_object)) { + int array_size = cJSON_GetArraySize(value_object); + if (array_size > sizeof(radio_cap->he_phy_cap)) { + array_size = sizeof(radio_cap->he_phy_cap); + } + for (int j = 0; j < array_size; j++) { + cJSON *array_item = cJSON_GetArrayItem(value_object, j); + if (cJSON_IsNumber(array_item)) { + radio_cap->he_phy_cap[j] = (uint8_t)array_item->valuedouble; + } + } + } + + value_object = cJSON_GetObjectItem(object, "HEMACCap"); + if (value_object != NULL && cJSON_IsArray(value_object)) { + int array_size = cJSON_GetArraySize(value_object); + if (array_size > sizeof(radio_cap->he_mac_cap)) { + array_size = sizeof(radio_cap->he_mac_cap); + } + for (int j = 0; j < array_size; j++) { + cJSON *array_item = cJSON_GetArrayItem(value_object, j); + if (cJSON_IsNumber(array_item)) { + radio_cap->he_mac_cap[j] = (uint8_t)array_item->valuedouble; + } + } + } + + value_object = cJSON_GetObjectItem(object, "HEMCSNSSSet"); + if (value_object != NULL && cJSON_IsArray(value_object)) { + int array_size = cJSON_GetArraySize(value_object); + if (array_size > sizeof(radio_cap->he_mcs_nss_set)) { + array_size = sizeof(radio_cap->he_mcs_nss_set); + } + for (int j = 0; j < array_size; j++) { + cJSON *array_item = cJSON_GetArrayItem(value_object, j); + if (cJSON_IsNumber(array_item)) { + radio_cap->he_mcs_nss_set[j] = (uint8_t)array_item->valuedouble; + } + } + } + + value_object = cJSON_GetObjectItem(object, "HEPPET"); + if (value_object != NULL && cJSON_IsArray(value_object)) { + int array_size = cJSON_GetArraySize(value_object); + if (array_size > sizeof(radio_cap->he_ppet)) { + array_size = sizeof(radio_cap->he_ppet); + } + for (int j = 0; j < array_size; j++) { + cJSON *array_item = cJSON_GetArrayItem(value_object, j); + if (cJSON_IsNumber(array_item)) { + radio_cap->he_ppet[j] = (uint8_t)array_item->valuedouble; + } + } + } + + //decode_param_integer(cap_obj, "HE6GHzCapa", param); + //if (param != NULL && cJSON_IsNumber(param)) { + // radio_cap->he_cap.6ghz_capa = (USHORT)param->valuedouble; + //} +#endif /* CONFIG_IEEE80211AX */ + +#ifdef CONFIG_IEEE80211BE + decode_param_bool(object, "WiFi7Supported", value_object); + if (value_object != NULL) { + radio_cap->wifi7_supported = (value_object->type & cJSON_True) ? true : false; + } + + value_object = cJSON_GetObjectItem(object, "EHTMACCap"); + if (value_object != NULL && cJSON_IsNumber(value_object)) { + radio_cap->eht_mac_cap = (UCHAR)value_object->valuedouble; + } + + value_object = cJSON_GetObjectItem(object, "EHTPHYCap"); + if (value_object != NULL && cJSON_IsArray(value_object)) { + int array_size = cJSON_GetArraySize(value_object); + if ((size_t)array_size > sizeof(radio_cap->eht_phy_cap)) { + array_size = sizeof(radio_cap->eht_phy_cap); + } + for (int j = 0; j < array_size; j++) { + cJSON *array_item = cJSON_GetArrayItem(value_object, j); + if (cJSON_IsNumber(array_item)) { + radio_cap->eht_phy_cap[j] = (UCHAR)array_item->valuedouble; + } + } + } + + value_object = cJSON_GetObjectItem(object, "EHTMCS"); + if (value_object != NULL && cJSON_IsArray(value_object)) { + int array_size = cJSON_GetArraySize(value_object); + if ((size_t)array_size > sizeof(radio_cap->eht_mcs)) { + array_size = sizeof(radio_cap->eht_mcs); + } + for (int j = 0; j < array_size; j++) { + cJSON *array_item = cJSON_GetArrayItem(value_object, j); + if (cJSON_IsNumber(array_item)) { + radio_cap->eht_mcs[j] = (UCHAR)array_item->valuedouble; + } + } + } + + value_object = cJSON_GetObjectItem(object, "EHTPPET"); + if (value_object != NULL && cJSON_IsArray(value_object)) { + int array_size = cJSON_GetArraySize(value_object); + if ((size_t)array_size > sizeof(radio_cap->eht_ppet)) { + array_size = sizeof(radio_cap->eht_ppet); + } + for (int j = 0; j < array_size; j++) { + cJSON *array_item = cJSON_GetArrayItem(value_object, j); + if (cJSON_IsNumber(array_item)) { + radio_cap->eht_ppet[j] = (UCHAR)array_item->valuedouble; + } + } + } +#endif /* CONFIG_IEEE80211BE */ } return webconfig_error_none; } diff --git a/source/webconfig/wifi_easymesh_translator.c b/source/webconfig/wifi_easymesh_translator.c index e946dcdc8..f09413f3b 100644 --- a/source/webconfig/wifi_easymesh_translator.c +++ b/source/webconfig/wifi_easymesh_translator.c @@ -274,6 +274,7 @@ webconfig_error_t translate_device_object_to_easymesh_for_dml(webconfig_subdoc 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) { @@ -388,6 +389,121 @@ webconfig_error_t translate_radio_object_to_easymesh_for_radio(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(wifi_platform_property_t *wifi_prop, + int radio_index, + em_radio_cap_info_t *cap_info) +{ + wifi_radio_capabilities_t *radio_cap; + em_radio_wifi6_cap_data_t *wifi6_cap; + em_wifi7_agent_cap_t *wifi7_cap; + em_wifi7_mlo_cap_support_tlv_t *wifi7_radio; + unsigned int i; + const unsigned char *phy; + const unsigned char *mac; + + if (cap_info == NULL) { + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d: NULL pointer or get_radio_cap not set\n", __func__, __LINE__); + return webconfig_error_translate_to_easymesh; + } + + radio_cap = &wifi_prop->radiocap[radio_index]; + wifi6_cap = &cap_info->wifi6_cap; + wifi7_cap = &cap_info->wifi7_cap; + + memset(wifi6_cap, 0, sizeof(*wifi6_cap)); + + if (radio_cap->wifi6_supported) { + mac_addr_str_t mac_str; + uint8_mac_to_string_mac(cap_info->ruid.mac, mac_str); + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d: radio_cap index: %d and mac:%s and radio_index:%d\n", __func__, + __LINE__, radio_index, mac_str, radio_index); + + phy = radio_cap->he_phy_cap; + mac = radio_cap->he_mac_cap; + + //AP role + wifi6_cap->num_role = 1; + for (int role = 0; role < wifi6_cap->num_role; role++) { + wifi6_cap->roles[role].role_head.agent_role = 0; /* AP */ + + /* HE PHY: Channel width (byte 0) */ + wifi6_cap->roles[role].role_head.he_160 = (phy[0] & (1u << HE_PHY_CHAN_WIDTH_160_BIT)) ? 1 : 0; + wifi6_cap->roles[role].role_head.he_8080 = (phy[0] & (1u << HE_PHY_CHAN_WIDTH_80P80_BIT)) ? 1 : 0; + + /* HE PHY: Beamforming (bytes 3, 4, 5, 6) */ + wifi6_cap->roles[role].role_tail.su_beam_former = (phy[3] & (1u << HE_PHY_SU_BEAMFORMER_BIT)) ? 1 : 0; + wifi6_cap->roles[role].role_tail.su_beam_formee = (phy[4] & (1u << HE_PHY_SU_BEAMFORMEE_BIT)) ? 1 : 0; + wifi6_cap->roles[role].role_tail.mu_beam_former = (phy[4] & (1u << HE_PHY_MU_BEAMFORMER_BIT)) ? 1 : 0; + wifi6_cap->roles[role].role_tail.beam_formee_sts_l80 = (phy[5] & 0x38u) ? 1 : 0; /* Nr bits 3-5 */ + wifi6_cap->roles[role].role_tail.beam_formee_sts_g80 = (phy[6] & 0x38u) ? 1 : 0; /* Nr bits 3-5 for >80MHz */ + + /* HE PHY byte 8: Number of RX/TX HE-MIMO-LTF (4 bits each) */ + wifi6_cap->roles[role].role_tail.max_ul_mumimo_rx = phy[8] & 0x0Fu; + wifi6_cap->roles[role].role_tail.max_dl_mumimo_tx = (phy[8] >> 4) & 0x0Fu; + + /* HE MAC: OFDMA (byte 2 in 4-byte mac_cap); UL MU-MIMO inferred from PHY */ + wifi6_cap->roles[role].role_tail.dl_ofdma = (mac[2] & (1u << HE_MAC_DL_OFDMA_BIT)) ? 1 : 0; + wifi6_cap->roles[role].role_tail.ul_ofdma = (mac[2] & (1u << HE_MAC_UL_OFDMA_BIT)) ? 1 : 0; + wifi6_cap->roles[role].role_tail.ul_mumimo = (wifi6_cap->roles[role].role_tail.max_ul_mumimo_rx != 0) ? 1 : 0; + + /* HE MAC byte 5 (not in rdk 4-byte mac_cap): max OFDMA RU; use 0 or skip */ + wifi6_cap->roles[role].role_tail.max_dl_ofdma_tx = 0; + wifi6_cap->roles[role].role_tail.max_ul_ofdma_rx = 0; + + /* HE MAC: TWT (byte 0) */ + wifi6_cap->roles[role].role_tail.twt_req = (mac[0] & (1u << HE_MAC_TWT_REQ_BIT)) ? 1 : 0; + wifi6_cap->roles[role].role_tail.twt_resp = (mac[0] & (1u << HE_MAC_TWT_RESP_BIT)) ? 1 : 0; + + wifi6_cap->roles[role].role_tail.anticipated_channel_usage = 0; + wifi6_cap->roles[role].role_tail.spatial_reuse = 0; + wifi6_cap->roles[role].role_tail.mu_edca = 0; + wifi6_cap->roles[role].role_tail.multi_bssid = 0; + wifi6_cap->roles[role].role_tail.mu_rts = 0; + wifi6_cap->roles[role].role_tail.rts = 0; + + /* MCS NSS: rdk has mcs_nss_set[6] -> 3 x uint16 (LE) */ + wifi6_cap->roles[role].role_head.mcs_nss_num = 3; + for (i = 0; i < 3 && i < MAX_MCS_NSS; i++) { + wifi6_cap->roles[role].mcs_nss[i] = (unsigned short)radio_cap->he_mcs_nss_set[i * 2] + | ((unsigned short)radio_cap->he_mcs_nss_set[i * 2 + 1] << 8); + } + } + } + + memset(wifi7_cap, 0, sizeof(*wifi7_cap)); + if (radio_cap->wifi7_supported) { + wifi7_radio = &wifi7_cap->mlo_cap_support; + memset(wifi7_radio, 0, sizeof(*wifi7_radio)); + memcpy(wifi7_radio->ruid, cap_info->ruid.mac, sizeof(mac_address_t)); + + unsigned short eht_mac = (unsigned short)radio_cap->eht_mac_cap; + (void)eht_mac; + + /* Extract WiFi 7 Multi-Link modes from mldOperationalCap */ + wifi_multi_link_modes_t mld_modes = radio_cap->mldOperationalCap; + + /* AP mode support */ + wifi7_radio->ap_str_support = (mld_modes & STR) ? 1 : 0; + wifi7_radio->ap_nstr_support = (mld_modes & NSTR) ? 1 : 0; + wifi7_radio->ap_emlsr_support = (mld_modes & eMLSR) ? 1 : 0; + wifi7_radio->ap_emlmr_support = (mld_modes & eMLMR) ? 1 : 0; + + /* BSTA (Backhaul STA) mode support */ + wifi7_radio->bsta_str_support = (mld_modes & STR) ? 1 : 0; + wifi7_radio->bsta_nstr_support = (mld_modes & NSTR) ? 1 : 0; + wifi7_radio->bsta_emlsr_support = (mld_modes & eMLSR) ? 1 : 0; + wifi7_radio->bsta_emlmr_support = (mld_modes & eMLMR) ? 1 : 0; + + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d: ap_str_support: %d, ap_nstr_support: %d, ap_emlsr_support: %d, \ + ap_emlmr_support: %d, bsta_str_support: %d, bsta_nstr_support: %d, bsta_emlsr_support: %d, bsta_emlmr_support: %d\n", __func__, \ + __LINE__, wifi7_radio->ap_str_support, wifi7_radio->ap_nstr_support, wifi7_radio->ap_emlsr_support, wifi7_radio->ap_emlmr_support, \ + wifi7_radio->bsta_str_support, wifi7_radio->bsta_nstr_support, wifi7_radio->bsta_emlsr_support, wifi7_radio->bsta_emlmr_support); + } + + return webconfig_error_none; +} + // This routine converts DML webconfig subdoc values to em_radio_list_t,em_radio_info_t easymesh structures webconfig_error_t translate_radio_object_to_easymesh_for_dml(webconfig_subdoc_data_t *data) { @@ -401,6 +517,7 @@ webconfig_error_t translate_radio_object_to_easymesh_for_dml(webconfig_subdoc_da webconfig_external_easymesh_t *proto; wifi_radio_operationParam_t *oper_param; webconfig_subdoc_decoded_data_t *decoded_params; + mac_addr_str_t mac_str; decoded_params = &data->u.decoded; if (decoded_params == NULL) { @@ -506,6 +623,19 @@ webconfig_error_t translate_radio_object_to_easymesh_for_dml(webconfig_subdoc_da em_radio_info->associated_sta_link_mterics_inclusion_policy = 0; strncpy (em_radio_info->chip_vendor, wifi_prop->manufacturer, strlen(em_radio_info->chip_vendor)); + em_radio_cap_info_t *radio_cap = proto->get_radio_cap(proto->data_model, wifi_prop->radiocap[index].rdk_radio_index); + if (radio_cap == NULL) { + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d: radio_cap not found\n", __func__, __LINE__); + return webconfig_error_translate_to_easymesh; + } + if (radio_iface_map->radio_index == wifi_prop->radiocap[index].rdk_radio_index) { + memcpy(radio_cap->ruid.mac, em_radio_info->intf.mac, sizeof(mac_address_t)); + uint8_mac_to_string_mac(radio_cap->ruid.mac, mac_str); + wifi_util_error_print(WIFI_WEBCONFIG, "%s:%d: radio_cap index: %d and mac:%s and radio_index:%d\n", __func__, + __LINE__, index, mac_str, radio_index); + + translate_radio_capability_to_easymesh(wifi_prop, radio_index, radio_cap); + } } return webconfig_error_none; @@ -2991,7 +3121,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 +3148,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 d3c74da89..3e1fbdd7d 100644 --- a/source/webconfig/wifi_encoder.c +++ b/source/webconfig/wifi_encoder.c @@ -2327,7 +2327,8 @@ webconfig_error_t encode_wifiradiocap(wifi_platform_property_t *wifi_prop, cJSON radiocap = &wifi_prop->radiocap[i]; object = cJSON_CreateObject(); cJSON_AddItemToArray(radio_obj, object); - cJSON_AddNumberToObject(object, "RadioIndex", radiocap->index); + cJSON_AddNumberToObject(object, "PhyIndex", radiocap->index); + cJSON_AddNumberToObject(object, "RadioIndex", radiocap->rdk_radio_index); for (freq_band_count = 0; freq_band_count < radiocap->numSupportedFreqBand; freq_band_count++) { (void)memcpy(channels_list, radiocap->channel_list[freq_band_count].channels_list, sizeof(*channels_list) * radiocap->channel_list[freq_band_count].num_channels); @@ -2347,6 +2348,62 @@ webconfig_error_t encode_wifiradiocap(wifi_platform_property_t *wifi_prop, cJSON } cJSON_AddNumberToObject(object, "RadioPresence", wifi_prop->radio_presence[i]); + +#ifdef CONFIG_IEEE80211AX + /* WiFi6 (HE) capabilities */ + cJSON_AddBoolToObject(object, "WiFi6Supported", wifi_prop->radiocap[i].wifi6_supported); + + cJSON *he_phy_cap_array = cJSON_CreateArray(); + for (int j = 0; j < HE_MAX_PHY_CAPAB_SIZE; j++) { + cJSON_AddItemToArray(he_phy_cap_array, cJSON_CreateNumber(wifi_prop->radiocap[i].he_phy_cap[j])); + } + cJSON_AddItemToObject(object, "HEPHYCap", he_phy_cap_array); + + cJSON *he_mac_cap_array = cJSON_CreateArray(); + for (int j = 0; j < HE_MAX_MAC_CAPAB_SIZE; j++) { + cJSON_AddItemToArray(he_mac_cap_array, cJSON_CreateNumber(wifi_prop->radiocap[i].he_mac_cap[j])); + } + cJSON_AddItemToObject(object, "HEMACCap", he_mac_cap_array); + + cJSON *he_mcs_nss_array = cJSON_CreateArray(); + for (int j = 0; j < HE_MAX_MCS_CAPAB_SIZE; j++) { + cJSON_AddItemToArray(he_mcs_nss_array, cJSON_CreateNumber(wifi_prop->radiocap[i].he_mcs_nss_set[j])); + } + cJSON_AddItemToObject(object, "HEMCSNSSSet", he_mcs_nss_array); + + cJSON *he_ppet_array = cJSON_CreateArray(); + for (int j = 0; j < HE_MAX_PPET_CAPAB_SIZE; j++) { + cJSON_AddItemToArray(he_ppet_array, cJSON_CreateNumber(wifi_prop->radiocap[i].he_ppet[j])); + } + cJSON_AddItemToObject(object, "HEPPET", he_ppet_array); + + //cJSON_AddNumberToObject(object, "HE6GHzCapa", wifi_prop->radiocap[i].6ghz_capa); +#endif /* CONFIG_IEEE80211AX */ + +#ifdef CONFIG_IEEE80211BE + /* WiFi7 (EHT) capabilities */ + cJSON_AddBoolToObject(object, "WiFi7Supported", wifi_prop->radiocap[i].wifi7_supported); + + cJSON_AddNumberToObject(object, "EHTMACCap", wifi_prop->radiocap[i].eht_mac_cap); + + cJSON *eht_phy_cap_array = cJSON_CreateArray(); + for (int j = 0; j < EHT_PHY_CAPAB_LEN; j++) { + cJSON_AddItemToArray(eht_phy_cap_array, cJSON_CreateNumber(wifi_prop->radiocap[i].eht_phy_cap[j])); + } + cJSON_AddItemToObject(object, "EHTPHYCap", eht_phy_cap_array); + + cJSON *eht_mcs_array = cJSON_CreateArray(); + for (int j = 0; j < EHT_MCS_NSS_CAPAB_LEN; j++) { + cJSON_AddItemToArray(eht_mcs_array, cJSON_CreateNumber(wifi_prop->radiocap[i].eht_mcs[j])); + } + cJSON_AddItemToObject(object, "EHTMCS", eht_mcs_array); + + cJSON *eht_ppet_array = cJSON_CreateArray(); + for (int j = 0; j < EHT_PPE_THRESH_CAPAB_LEN; j++) { + cJSON_AddItemToArray(eht_ppet_array, cJSON_CreateNumber(wifi_prop->radiocap[i].eht_ppet[j])); + } + cJSON_AddItemToObject(object, "EHTPPET", eht_ppet_array); +#endif /* CONFIG_IEEE80211BE */ } return webconfig_error_none; }