/** * @brief This function parses country info from AP and * download country info to FW * * @param pmpriv A pointer to mlan_private structure * @param pbss_desc A pointer to BSS descriptor * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_11d_parse_dnld_countryinfo(mlan_private * pmpriv, BSSDescriptor_t * pbss_desc) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_adapter *pmadapter = pmpriv->adapter; parsed_region_chan_11d_t region_chan; parsed_region_chan_11d_t bssdesc_region_chan; t_u32 i, j; ENTER(); /* Only valid if 11D is enabled */ if (wlan_11d_get_state(pmpriv) == ENABLE_11D) { memset(pmadapter, &pmadapter->domain_reg, 0, sizeof(wlan_802_11d_domain_reg_t)); memset(pmadapter, ®ion_chan, 0, sizeof(parsed_region_chan_11d_t)); memset(pmadapter, &bssdesc_region_chan, 0, sizeof(parsed_region_chan_11d_t)); memcpy(pmadapter, ®ion_chan, &pmadapter->parsed_region_chan, sizeof(parsed_region_chan_11d_t)); if (pbss_desc) { /* Parse domain info if available */ ret = wlan_11d_parse_domain_info(pmadapter, &pbss_desc->country_info, pbss_desc->bss_band, &bssdesc_region_chan); if (ret == MLAN_STATUS_SUCCESS) { /* Update the channel-power table */ for (i = 0; ((i < bssdesc_region_chan.no_of_chan) && (i < MAX_NO_OF_CHAN)); i++) { for (j = 0; ((j < region_chan.no_of_chan) && (j < MAX_NO_OF_CHAN)); j++) { /* * Channel already exists, so overwrite existing * tx power with the tx_power received from * country info of the current AP */ if (region_chan.chan_pwr[i].chan == bssdesc_region_chan.chan_pwr[j].chan) { region_chan.chan_pwr[j].pwr = bssdesc_region_chan.chan_pwr[i].pwr; break; } } } } } /* Generate domain info */ wlan_11d_generate_domain_info(pmadapter, ®ion_chan, &pmadapter->domain_reg); /* Set domain info */ ret = wlan_11d_set_domain_info(pmpriv); if (ret) { PRINTM(MERROR, "11D: Error setting domain info in FW\n"); } } LEAVE(); return ret; }
/** * @brief This function processes the country info present in BSSDescriptor. * * @param pmpriv A pointer to mlan_private structure * @param pbss_desc A pointer to BSSDescriptor_t * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_11d_process_country_info(mlan_private * pmpriv, BSSDescriptor_t * pbss_desc) { mlan_adapter *pmadapter = pmpriv->adapter; parsed_region_chan_11d_t region_chan; parsed_region_chan_11d_t *parsed_region_chan = &pmadapter->parsed_region_chan; t_u16 i, j, num_chan_added = 0; ENTER(); memset(pmadapter, ®ion_chan, 0, sizeof(parsed_region_chan_11d_t)); /* Parse 11D country info */ if (wlan_11d_parse_domain_info(pmadapter, &pbss_desc->country_info, (t_u8) pbss_desc->bss_band, ®ion_chan) != MLAN_STATUS_SUCCESS) return MLAN_STATUS_FAILURE; memcpy(pmadapter, parsed_region_chan->country_code, ®ion_chan.country_code, COUNTRY_CODE_LEN); if (parsed_region_chan->no_of_chan != 0) { /* * Check if the channel number already exists in the * chan-power table of parsed_region_chan */ for (i = 0; (i < region_chan.no_of_chan && i < MAX_NO_OF_CHAN); i++) { for (j = 0; (j < parsed_region_chan->no_of_chan && j < MAX_NO_OF_CHAN); j++) { /* * Channel already exists, update the tx power with new tx * power, since country IE is valid here. */ if (region_chan.chan_pwr[i].chan == parsed_region_chan->chan_pwr[j].chan) { parsed_region_chan->chan_pwr[j].pwr = region_chan.chan_pwr[i].pwr; break; } } if (j == parsed_region_chan->no_of_chan && j < MAX_NO_OF_CHAN) { /* * Channel does not exist in the channel power table, * update this new chan and tx_power to the channel power table */ parsed_region_chan->chan_pwr[parsed_region_chan->no_of_chan + num_chan_added].chan = region_chan.chan_pwr[i].chan; parsed_region_chan->chan_pwr[parsed_region_chan->no_of_chan + num_chan_added].pwr = region_chan.chan_pwr[i].pwr; num_chan_added++; } } parsed_region_chan->no_of_chan += num_chan_added; } else { /* Parsed region is empty, copy the first one */ memcpy(pmadapter, parsed_region_chan, ®ion_chan, sizeof(parsed_region_chan_11d_t)); } LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief This function parses country info from AP and * download country info to FW * * @param pmpriv A pointer to mlan_private structure * @param pbss_desc A pointer to BSS descriptor * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_11d_parse_dnld_countryinfo(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_adapter *pmadapter = pmpriv->adapter; parsed_region_chan_11d_t region_chan; parsed_region_chan_11d_t bssdesc_region_chan; t_u32 i, j; ENTER(); /* Only valid if 11D is enabled */ if (wlan_11d_is_enabled(pmpriv)) { memset(pmadapter, ®ion_chan, 0, sizeof(parsed_region_chan_11d_t)); memset(pmadapter, &bssdesc_region_chan, 0, sizeof(parsed_region_chan_11d_t)); memcpy(pmadapter, ®ion_chan, &pmadapter->parsed_region_chan, sizeof(parsed_region_chan_11d_t)); if (pbss_desc) { /* Parse domain info if available */ ret = wlan_11d_parse_domain_info(pmadapter, &pbss_desc-> country_info, (t_u8)pbss_desc-> bss_band, &bssdesc_region_chan); if (ret == MLAN_STATUS_SUCCESS) { /* Update the channel-power table */ for (i = 0; ((i < bssdesc_region_chan.no_of_chan) && (i < MAX_NO_OF_CHAN)); i++) { for (j = 0; ((j < region_chan.no_of_chan) && (j < MAX_NO_OF_CHAN)); j++) { /* * Channel already exists, use minimum * of existing tx power and tx_power * received from country info of the * current AP */ if (region_chan.chan_pwr[i]. chan == bssdesc_region_chan. chan_pwr[j].chan && region_chan.chan_pwr[i]. band == bssdesc_region_chan. chan_pwr[j].band) { region_chan.chan_pwr[j]. pwr = MIN(region_chan. chan_pwr[j]. pwr, bssdesc_region_chan. chan_pwr[i]. pwr); break; } } } } } /* Generate domain info */ wlan_11d_generate_domain_info(pmadapter, ®ion_chan); /* Set domain info */ ret = wlan_11d_send_domain_info(pmpriv, MNULL); if (ret) { PRINTM(MERROR, "11D: Error sending domain info to FW\n"); } } LEAVE(); return ret; }