/** * @brief This function handles domain info data from UAP interface. * Checks conditions, sets up domain_reg, then downloads CMD. * * @param pmpriv A pointer to mlan_private structure * @param band Band interface is operating on * @param domain_tlv Pointer to domain_info tlv * @param pioctl_buf Pointer to the IOCTL buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_11d_handle_uap_domain_info(mlan_private * pmpriv, t_u8 band, t_u8 * domain_tlv, t_void * pioctl_buf) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_adapter *pmadapter = pmpriv->adapter; MrvlIEtypes_DomainParamSet_t *pdomain_tlv; t_u8 num_sub_band = 0; t_u8 region_code = 0; ENTER(); pdomain_tlv = (MrvlIEtypes_DomainParamSet_t *) domain_tlv; // update region code & table based on country string if (wlan_11d_region_2_code(pmadapter, pdomain_tlv->country_code, ®ion_code) == MLAN_STATUS_SUCCESS) { pmadapter->region_code = region_code; ret = wlan_set_regiontable(pmpriv, region_code, pmadapter->fw_bands); } num_sub_band = ((pdomain_tlv->header.len - COUNTRY_CODE_LEN) / sizeof(IEEEtypes_SubbandSet_t)); // TODO: don't just clobber pmadapter->domain_reg. // Add some checking or merging between STA & UAP domain_info wlan_11d_set_domain_info(pmpriv, band, pdomain_tlv->country_code, num_sub_band, pdomain_tlv->sub_band); ret = wlan_11d_send_domain_info(pmpriv, pioctl_buf); LEAVE(); return ret; }
/** * @brief This function parses country information for region channel * * @param pmadapter Pointer to mlan_adapter structure * @param country_info Country information * @param band Chan band * @param parsed_region_chan Pointer to parsed_region_chan_11d_t * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_11d_parse_domain_info(pmlan_adapter pmadapter, IEEEtypes_CountryInfoFullSet_t * country_info, t_u8 band, parsed_region_chan_11d_t * parsed_region_chan) { t_u8 no_of_sub_band, no_of_chan; t_u8 last_chan, first_chan, cur_chan = 0; t_u8 idx = 0; t_u8 j, i; ENTER(); /* * Validation Rules: * 1. Valid Region Code * 2. First Chan increment * 3. Channel range no overlap * 4. Channel is valid? * 5. Channel is supported by Region? * 6. Others */ HEXDUMP("country_info", (t_u8 *) country_info, 30); if (!(*(country_info->country_code)) || (country_info->len <= COUNTRY_CODE_LEN)) { /* No region info or wrong region info: treat as no 11D info */ LEAVE(); return MLAN_STATUS_FAILURE; } /* Step 1: Check region_code */ parsed_region_chan->region = wlan_11d_region_2_code(pmadapter, country_info->country_code); PRINTM(MINFO, "11D: region code=0x%x\n", (t_u8) parsed_region_chan->region); HEXDUMP("11D: Country Code", (t_u8 *) country_info->country_code, COUNTRY_CODE_LEN); parsed_region_chan->band = band; memcpy(pmadapter, parsed_region_chan->country_code, country_info->country_code, COUNTRY_CODE_LEN); no_of_sub_band = (country_info->len - COUNTRY_CODE_LEN) / sizeof(IEEEtypes_SubbandSet_t); for (j = 0, last_chan = 0; j < no_of_sub_band; j++) { if (country_info->sub_band[j].first_chan <= last_chan) { /* Step2&3: Check First Chan Num increment and no overlap */ PRINTM(MINFO, "11D: Chan[%d>%d] Overlap\n", country_info->sub_band[j].first_chan, last_chan); continue; } first_chan = country_info->sub_band[j].first_chan; no_of_chan = country_info->sub_band[j].no_of_chan; for (i = 0; idx < MAX_NO_OF_CHAN && i < no_of_chan; i++) { /* Step 4 : Channel is supported? */ if (wlan_11d_get_chan(pmadapter, band, first_chan, i, &cur_chan) == MFALSE) { /* Chan is not found in UN table */ PRINTM(MWARN, "11D: channel is not supported: %d\n", i); break; } last_chan = cur_chan; /* Step 5: We don't need to check if cur_chan is supported by mrvl in region */ parsed_region_chan->chan_pwr[idx].chan = cur_chan; parsed_region_chan->chan_pwr[idx].pwr = country_info->sub_band[j].max_tx_pwr; idx++; } /* Step 6: Add other checking if any */ } parsed_region_chan->no_of_chan = idx; PRINTM(MINFO, "11D: number of channel=0x%x\n", parsed_region_chan->no_of_chan); HEXDUMP("11D: parsed_region_chan", (t_u8 *) parsed_region_chan, 2 + COUNTRY_CODE_LEN + sizeof(parsed_region_chan_11d_t) * idx); LEAVE(); return MLAN_STATUS_SUCCESS; }