/** * @brief Perform a radar measurement and report the result if required on * given channel * * Check to see if the provided channel requires a channel availability * check (60 second radar detection measurement). If required, perform * measurement, stalling calling thread until the measurement completes * and then report result. * * Used when starting an adhoc network. * * @param priv Private driver information structure * @param channel Channel on which to perform radar measurement * * @return * - MTRUE if radar has been detected * - MFALSE if radar detection is not required or radar has not been detected * * @sa wlan_11h_radar_detect_required */ int wlan_11h_radar_detected(mlan_private * priv, t_u8 channel) { int ret; HostCmd_DS_MEASUREMENT_REQUEST meas_req; HostCmd_DS_MEASUREMENT_REPORT meas_rpt; ENTER(); /* * If the channel requires radar, default the return value to it being * detected. */ ret = wlan_11h_radar_detect_required(priv, channel); memset(&meas_req, 0x00, sizeof(meas_req)); memset(&meas_rpt, 0x00, sizeof(meas_rpt)); /* * Send a basic measurement request on the indicated channel for the * required channel availability check time. */ meas_req.meas_type = WLAN_MEAS_BASIC; meas_req.req.basic.channel = channel; meas_req.req.basic.duration = WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION; /* * Set the STA that we are requesting the measurement from to our own * mac address, causing our firmware to perform the measurement itself */ memcpy(meas_req.mac_addr, priv->curr_addr, sizeof(meas_req.mac_addr)); /* * Send the measurement request and timeout duration to wait for * the command to spend until the measurement report is received * from the firmware. If the command fails, the default ret value set * above will be returned. */ if (!wlan_meas_util_send_req(priv, &meas_req, meas_req.req.basic.duration, &meas_rpt)) { /* * If the report indicates no measurement was done, leave the default * return value alone. */ if (!meas_rpt.rpt.basic.map.unmeasured) /* * Set the return value based on the radar indication bit */ ret = meas_rpt.rpt.basic.map.radar ? MTRUE : MFALSE; } LEAVE(); return ret; }
/** * @brief Callback to finish 11H channel check handling. * Not to be called directly to initiate channel check. * * @param priv A pointer to mlan_private structure (cast from t_void*) * * @return MLAN_STATUS_SUCCESS/PENDING --success, otherwise fail * @sa wlan_uap_11h_channel_check_req */ static mlan_status wlan_uap_callback_11h_channel_check_req(IN t_void * priv) { mlan_status ret = MLAN_STATUS_FAILURE; mlan_private *pmpriv = (mlan_private *) priv; mlan_callbacks *pcb = (mlan_callbacks *) & pmpriv->adapter->callbacks; wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb; /* keep copy as local variable */ pmlan_ioctl_req pioctl = puap_state_chan_cb->pioctl_req_curr; ENTER(); /* clear callback now that we're here */ puap_state_chan_cb->get_chan_callback = MNULL; /* clear early to avoid race condition */ puap_state_chan_cb->pioctl_req_curr = MNULL; /* * Check if the region and channel requires a channel availability * check. */ if ((puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) && wlan_11h_radar_detect_required(pmpriv, puap_state_chan_cb->channel) && !wlan_11h_is_channel_under_nop(pmpriv->adapter, puap_state_chan_cb->channel)) { /* * Radar detection is required for this channel, make sure * 11h is activated in the firmware */ ret = wlan_11h_activate(pmpriv, MNULL, MTRUE); ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE); ret = wlan_11h_check_update_radar_det_state(pmpriv); /* Check for radar on the channel */ ret = wlan_11h_issue_radar_detect(pmpriv, pioctl, puap_state_chan_cb->channel); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; } else { /* No command sent with the ioctl, need manually signal completion */ pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle, pioctl, MLAN_STATUS_FAILURE); } LEAVE(); return ret; }
/** * @brief This function Checks if channel txpwr is learned from AP/IBSS * * @param pmadapter A pointer to mlan_adapter structure * @param band Band number * @param chan Channel number * @param parsed_region_chan Pointer to parsed_region_chan_11d_t * * @return MTRUE or MFALSE */ static t_u8 wlan_11d_channel_known(pmlan_adapter pmadapter, t_u8 band, t_u8 chan, parsed_region_chan_11d_t * parsed_region_chan) { chan_power_11d_t *pchan_pwr = parsed_region_chan->chan_pwr; t_u8 no_of_chan = parsed_region_chan->no_of_chan; t_u8 i = 0; t_u8 ret = MFALSE; mlan_private *pmpriv; ENTER(); HEXDUMP("11D: parsed_region_chan", (t_u8 *) pchan_pwr, sizeof(chan_power_11d_t) * no_of_chan); /* Search channel */ for (i = 0; i < no_of_chan; i++) { if (chan == pchan_pwr[i].chan && band == pchan_pwr[i].band) { PRINTM(MINFO, "11D: Found channel:%d (band:%d)\n", chan, band); ret = MTRUE; if (band & BAND_A) { /* If chan is a DFS channel, we need to see an AP on it */ pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA); if (pmpriv && wlan_11h_radar_detect_required(pmpriv, chan)) { PRINTM(MINFO, "11H: DFS channel %d, and ap_seen=%d\n", chan, pchan_pwr[i].ap_seen); ret = pchan_pwr[i].ap_seen; } } LEAVE(); return ret; } } PRINTM(MINFO, "11D: Could not find channel:%d (band:%d)\n", chan, band); LEAVE(); return ret; }
/** * @brief Callback to finish 11H handling * Not to be called directly to initiate 11H setting. * * @param pmpriv A pointer to mlan_private structure (cast from t_void*) * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_snmp_mib_11h */ static mlan_status wlan_uap_callback_snmp_mib_11h(IN t_void * priv) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = (mlan_private *) priv; wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb; mlan_ds_snmp_mib *snmp; t_bool enable_11h; ENTER(); /* clear callback now that we're here */ puap_state_chan_cb->get_chan_callback = MNULL; snmp = (mlan_ds_snmp_mib *) puap_state_chan_cb->pioctl_req_curr->pbuf; enable_11h = (snmp->param.oid_value) ? MTRUE : MFALSE; if (enable_11h) { if ((puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) && wlan_11h_radar_detect_required(pmpriv, puap_state_chan_cb->channel)) { if (!wlan_11h_is_master_radar_det_active(pmpriv)) wlan_11h_config_master_radar_det(pmpriv, MTRUE); } } ret = wlan_11h_activate(pmpriv, (t_void *) puap_state_chan_cb->pioctl_req_curr, enable_11h); wlan_11h_check_update_radar_det_state(pmpriv); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; puap_state_chan_cb->pioctl_req_curr = MNULL; // prevent re-use LEAVE(); return ret; }
/** * @brief Callback to finish BSS IOCTL START * Not to be called directly to initiate bss_start * * @param priv A pointer to mlan_private structure (cast from t_void*) * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_bss_ioctl_start */ static mlan_status wlan_uap_callback_bss_ioctl_start(IN t_void * priv) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = (mlan_private *) priv; mlan_callbacks *pcb = (mlan_callbacks *) & pmpriv->adapter->callbacks; wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb; t_u8 old_channel; ENTER(); /* clear callback now that we're here */ puap_state_chan_cb->get_chan_callback = MNULL; /* * Check if the region and channel requires we check for radar. */ if ((puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) && wlan_11h_radar_detect_required(pmpriv, puap_state_chan_cb->channel)) { /* first check if channel is under NOP */ if (wlan_11h_is_channel_under_nop(pmpriv->adapter, puap_state_chan_cb->channel)) { /* recently we've seen radar on this channel */ ret = MLAN_STATUS_FAILURE; } /* Check cached radar check on the channel */ if (ret == MLAN_STATUS_SUCCESS) ret = wlan_11h_check_chan_report(pmpriv, puap_state_chan_cb->channel); /* Found radar: try to switch to a non-dfs channel */ if (ret != MLAN_STATUS_SUCCESS) { old_channel = puap_state_chan_cb->channel; ret = wlan_11h_switch_non_dfs_chan(pmpriv, &puap_state_chan_cb->channel); if (ret == MLAN_STATUS_SUCCESS) { ret = wlan_uap_set_channel(pmpriv, pmpriv->uap_state_chan_cb. band_config, puap_state_chan_cb->channel); if (ret == MLAN_STATUS_SUCCESS) { PRINTM(MMSG, "Radar found on channel %d," "switch to new channel %d.\n", old_channel, puap_state_chan_cb->channel); } else { PRINTM(MMSG, "Radar found on channel %d," " switch to new channel %d failed.\n", old_channel, puap_state_chan_cb->channel); pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle, puap_state_chan_cb-> pioctl_req_curr, MLAN_STATUS_FAILURE); goto done; } } else { PRINTM(MMSG, "Radar found on channel %d, no switch channel available.\n", old_channel); /* No command sent with the ioctl, need manually signal completion */ pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle, puap_state_chan_cb->pioctl_req_curr, MLAN_STATUS_FAILURE); goto done; } } else { PRINTM(MINFO, "No Radar found on channel %d\n", puap_state_chan_cb->channel); } } /* else okay to send command: not DFS channel or no radar */ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START, HostCmd_ACT_GEN_SET, 0, (t_void *) puap_state_chan_cb->pioctl_req_curr, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; done: puap_state_chan_cb->pioctl_req_curr = MNULL; // prevent re-use LEAVE(); return ret; }