/** * @brief This function prepares domain info from scan table and * downloads the domain info command to the FW. * * @param pmpriv A pointer to mlan_private structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_11d_prepare_dnld_domain_info_cmd(mlan_private * pmpriv) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_adapter *pmadapter = pmpriv->adapter; IEEEtypes_CountryInfoFullSet_t *pcountry_full = MNULL; t_u32 idx; ENTER(); /* Only valid if 11D is enabled */ if (wlan_11d_is_enabled(pmpriv) && pmadapter->num_in_scan_table != 0) { for (idx = 0; idx < pmadapter->num_in_scan_table; idx++) { pcountry_full = &pmadapter->pscan_table[idx].country_info; ret = wlan_11d_update_chan_pwr_table(pmpriv, &pmadapter-> pscan_table[idx]); if (*(pcountry_full->country_code) != 0 && (pcountry_full->len > COUNTRY_CODE_LEN)) { /* Country info found in the BSS Descriptor */ ret = wlan_11d_process_country_info(pmpriv, &pmadapter-> pscan_table [idx]); } } /* Sort parsed_region_chan in ascending channel number */ wlan_11d_sort_parsed_region_chan(&pmadapter-> parsed_region_chan); /* Check if connected */ if (pmpriv->media_connected == MTRUE) { ret = wlan_11d_parse_dnld_countryinfo(pmpriv, &pmpriv-> curr_bss_params. bss_descriptor); } else { ret = wlan_11d_parse_dnld_countryinfo(pmpriv, MNULL); } } LEAVE(); return ret; }
/** * @brief This function clears the parsed region table, if 11D is enabled * * @param pmpriv A pointer to mlan_private structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_11d_clear_parsedtable(mlan_private * pmpriv) { mlan_adapter *pmadapter = pmpriv->adapter; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); if (wlan_11d_is_enabled(pmpriv)) memset(pmadapter, &(pmadapter->parsed_region_chan), 0, sizeof(parsed_region_chan_11d_t)); else ret = MLAN_STATUS_FAILURE; LEAVE(); return ret; }
/** * @brief Set SNMP MIB for 11H * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_callback_snmp_mib_11h */ static mlan_status wlan_uap_snmp_mib_11h(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_snmp_mib *snmp = MNULL; t_bool enable; ENTER(); if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) { PRINTM(MWARN, "MLAN snmp_mib IOCTL length is too short.\n"); pioctl_req->data_read_written = 0; pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib); LEAVE(); return MLAN_STATUS_RESOURCE; } snmp = (mlan_ds_snmp_mib *) pioctl_req->pbuf; enable = (snmp->param.oid_value) ? MTRUE : MFALSE; if (enable) { /* first enable 11D if it is not enabled */ if (!wlan_11d_is_enabled(pmpriv)) { ret = wlan_11d_enable(pmpriv, MNULL, ENABLE_11D); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to first enable 11D before enabling 11H.\n"); LEAVE(); return ret; } } } /* store params, issue command to get UAP channel, whose CMD_RESP will callback remainder of 11H handling (and radar detect if DFS chan) */ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req; pmpriv->uap_state_chan_cb.get_chan_callback = wlan_uap_callback_snmp_mib_11h; ret = wlan_uap_get_channel(pmpriv); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; }
/** * @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; }
/** * @brief This function generates 11D info from user specified regioncode * and download to FW * * @param pmpriv A pointer to mlan_private structure * @param band Band to create * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_11d_create_dnld_countryinfo(mlan_private * pmpriv, t_u8 band) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_adapter *pmadapter = pmpriv->adapter; region_chan_t *region_chan; parsed_region_chan_11d_t parsed_region_chan; t_u8 j; ENTER(); /* Only valid if 11D is enabled */ if (wlan_11d_is_enabled(pmpriv)) { PRINTM(MINFO, "11D: Band[%d]\n", band); /* Update parsed_region_chan; download domain info to FW */ /* Find region channel */ for (j = 0; j < sizeof(pmadapter->region_channel) / sizeof(pmadapter->region_channel[0]); j++) { region_chan = &pmadapter->region_channel[j]; PRINTM(MINFO, "11D: [%d] region_chan->Band[%d]\n", j, region_chan->band); if (!region_chan || !region_chan->valid || !region_chan->pcfp) continue; switch (region_chan->band) { case BAND_A: switch (band) { case BAND_A: case BAND_AN: case BAND_A | BAND_AN: break; default: continue; } break; case BAND_B: case BAND_G: switch (band) { case BAND_B: case BAND_G: case BAND_G | BAND_B: case BAND_GN: case BAND_G | BAND_GN: case BAND_B | BAND_G | BAND_GN: break; default: continue; } break; default: continue; } break; } /* Check if region channel found */ if (j >= sizeof(pmadapter->region_channel) / sizeof(pmadapter->region_channel[0])) { PRINTM(MERROR, "11D: region_chan not found. Band[%d]\n", band); LEAVE(); return MLAN_STATUS_FAILURE; } /* Generate parsed region channel info from region channel */ memset(pmadapter, &parsed_region_chan, 0, sizeof(parsed_region_chan_11d_t)); wlan_11d_generate_parsed_region_chan(pmadapter, region_chan, &parsed_region_chan); /* Generate domain info from parsed region channel info */ wlan_11d_generate_domain_info(pmadapter, &parsed_region_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; }
/** * @brief This function handles disconnect event, reports disconnect * to upper layer, cleans tx/rx packets, * resets link state etc. * * @param priv A pointer to mlan_private structure * @param drv_disconnect Flag indicating the driver should disconnect * and flush pending packets. * * @return N/A */ t_void wlan_reset_connect_state(pmlan_private priv, t_u8 drv_disconnect) { mlan_adapter *pmadapter = priv->adapter; mlan_status ret = MLAN_STATUS_SUCCESS; state_11d_t enable; ENTER(); PRINTM(MINFO, "Handles disconnect event.\n"); if (drv_disconnect) { priv->media_connected = MFALSE; wlan_11h_check_update_radar_det_state(priv); } if (priv->port_ctrl_mode == MTRUE) { /* Close the port on Disconnect */ PRINTM(MINFO, "DISC: port_status = CLOSED\n"); priv->port_open = MFALSE; } pmadapter->scan_block = MFALSE; /* Reset SNR/NF/RSSI values */ priv->data_rssi_last = 0; priv->data_nf_last = 0; priv->data_rssi_avg = 0; priv->data_nf_avg = 0; priv->bcn_rssi_last = 0; priv->bcn_nf_last = 0; priv->bcn_rssi_avg = 0; priv->bcn_nf_avg = 0; priv->rxpd_rate = 0; priv->rxpd_rate_info = 0; priv->max_amsdu = 0; wlan_coex_ampdu_rxwinsize(pmadapter); priv->sec_info.ewpa_enabled = MFALSE; priv->sec_info.wpa_enabled = MFALSE; priv->sec_info.wpa2_enabled = MFALSE; priv->wpa_ie_len = 0; priv->sec_info.wapi_enabled = MFALSE; priv->wapi_ie_len = 0; priv->sec_info.wapi_key_on = MFALSE; priv->wps.session_enable = MFALSE; memset(priv->adapter, (t_u8 *)&priv->wps.wps_ie, 0x00, sizeof(priv->wps.wps_ie)); priv->sec_info.osen_enabled = MFALSE; priv->osen_ie_len = 0; priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE; /* Enable auto data rate */ priv->is_data_rate_auto = MTRUE; priv->data_rate = 0; if (priv->bss_mode == MLAN_BSS_MODE_IBSS) { priv->adhoc_state = ADHOC_IDLE; priv->adhoc_is_link_sensed = MFALSE; priv->intf_state_11h.adhoc_auto_sel_chan = MTRUE; } if (drv_disconnect) { /* Free Tx and Rx packets, report disconnect to upper layer */ wlan_clean_txrx(priv); /* Need to erase the current SSID and BSSID info */ memset(pmadapter, &priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params)); } wlan_send_tdls_tear_down_request(priv); wlan_delete_station_list(priv); pmadapter->tdls_status = TDLS_NOT_SETUP; priv->wmm_qosinfo = priv->saved_wmm_qosinfo; pmadapter->sleep_period.period = pmadapter->saved_sleep_period.period; pmadapter->tx_lock_flag = MFALSE; pmadapter->pps_uapsd_mode = MFALSE; pmadapter->delay_null_pkt = MFALSE; if ((wlan_11d_is_enabled(priv)) && (priv->state_11d.user_enable_11d == DISABLE_11D)) { priv->state_11d.enable_11d = DISABLE_11D; enable = DISABLE_11D; /* Send cmd to FW to enable/disable 11D function */ ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, HostCmd_ACT_GEN_SET, Dot11D_i, MNULL, &enable); if (ret) PRINTM(MERROR, "11D: Failed to enable 11D\n"); } if (pmadapter->num_cmd_timeout && pmadapter->curr_cmd && (pmadapter->cmd_timer_is_set == MFALSE)) { LEAVE(); return; } wlan_recv_event(priv, MLAN_EVENT_ID_FW_DISCONNECTED, MNULL); LEAVE(); }