| /** @file mlan_sta_cmdresp.c |
| * |
| * @brief This file contains the handling of command |
| * responses generated by firmware. |
| * |
| * Copyright (C) 2008-2009, Marvell International Ltd. |
| * All Rights Reserved |
| */ |
| |
| /****************************************************** |
| Change log: |
| 10/21/2008: initial version |
| ******************************************************/ |
| |
| #include "mlan.h" |
| #include "mlan_join.h" |
| #include "mlan_util.h" |
| #include "mlan_fw.h" |
| #include "mlan_main.h" |
| #include "mlan_wmm.h" |
| #include "mlan_11n.h" |
| #include "mlan_11h.h" |
| |
| #include "mlan_sdio.h" |
| |
| /******************************************************** |
| Local Variables |
| ********************************************************/ |
| |
| /******************************************************** |
| Global Variables |
| ********************************************************/ |
| |
| /******************************************************** |
| Local Functions |
| ********************************************************/ |
| /** |
| * @brief This function handles the command response error |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to command buffer |
| * |
| * @return N/A |
| */ |
| void |
| wlan_process_cmdresp_error(mlan_private * pmpriv, HostCmd_DS_COMMAND * resp, |
| mlan_ioctl_req * pioctl_buf) |
| { |
| cmd_ctrl_node *pcmd_node = MNULL; |
| mlan_adapter *pmadapter = pmpriv->adapter; |
| pmlan_callbacks pcb = &pmadapter->callbacks; |
| |
| ENTER(); |
| |
| PRINTM(MERROR, "CMD_RESP: cmd %#x error, result=%#x\n", resp->command, |
| resp->result); |
| if (pioctl_buf) |
| pioctl_buf->status_code = MLAN_ERROR_FW_CMDRESP; |
| |
| switch (resp->command) { |
| case HostCmd_CMD_802_11_PS_MODE_ENH: |
| { |
| HostCmd_DS_802_11_PS_MODE_ENH *pm = &resp->params.psmode_enh; |
| PRINTM(MERROR, |
| "PS_MODE_ENH command failed: result=0x%x action=0x%X\n", |
| resp->result, wlan_le16_to_cpu(pm->action)); |
| /* |
| * We do not re-try enter-ps command in ad-hoc mode. |
| */ |
| if (wlan_le16_to_cpu(pm->action) == EN_PS && |
| pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) |
| pmadapter->ps_mode = Wlan802_11PowerModeCAM; |
| } |
| break; |
| case HostCmd_CMD_802_11_SCAN: |
| /* Cancel all pending scan command */ |
| while ((pcmd_node = |
| (cmd_ctrl_node *) util_peek_list(&pmadapter->scan_pending_q, |
| pcb->moal_spin_lock, |
| pcb->moal_spin_unlock))) { |
| util_unlink_list(&pmadapter->scan_pending_q, |
| (pmlan_linked_list) pcmd_node, pcb->moal_spin_lock, |
| pcb->moal_spin_unlock); |
| pcmd_node->pioctl_buf = MNULL; |
| wlan_insert_cmd_to_free_q(pmadapter, pcmd_node); |
| } |
| wlan_request_cmd_lock(pmadapter); |
| pmadapter->scan_processing = MFALSE; |
| wlan_release_cmd_lock(pmadapter); |
| break; |
| |
| case HostCmd_CMD_MAC_CONTROL: |
| break; |
| |
| default: |
| break; |
| } |
| /* |
| * Handling errors here |
| */ |
| wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd); |
| |
| wlan_request_cmd_lock(pmadapter); |
| pmadapter->curr_cmd = MNULL; |
| wlan_release_cmd_lock(pmadapter); |
| |
| LEAVE(); |
| return; |
| } |
| |
| /** |
| * @brief This function handles the command response of get_hw_spec |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to command buffer |
| * |
| * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE |
| */ |
| static mlan_status |
| wlan_ret_get_hw_spec(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, IN t_void * pioctl_buf) |
| { |
| HostCmd_DS_GET_HW_SPEC *hw_spec = &resp->params.hw_spec; |
| mlan_adapter *pmadapter = pmpriv->adapter; |
| mlan_status ret = MLAN_STATUS_SUCCESS; |
| t_u32 i; |
| |
| ENTER(); |
| |
| pmadapter->fw_cap_info = wlan_le32_to_cpu(hw_spec->fw_cap_info); |
| |
| if (IS_SUPPORT_MULTI_BANDS(pmadapter)) { |
| pmadapter->fw_bands = (t_u8) GET_FW_DEFAULT_BANDS(pmadapter); |
| } else { |
| pmadapter->fw_bands = BAND_B; |
| } |
| |
| pmadapter->config_bands = pmadapter->fw_bands; |
| |
| if (pmadapter->fw_bands & BAND_A) { |
| if (pmadapter->fw_bands & BAND_GN) { |
| pmadapter->config_bands |= BAND_AN; |
| pmadapter->fw_bands |= BAND_AN; |
| } |
| if (pmadapter->fw_bands & BAND_AN) { |
| pmadapter->adhoc_start_band = BAND_A | BAND_AN; |
| pmadapter->adhoc_11n_enabled = MTRUE; |
| } else |
| pmadapter->adhoc_start_band = BAND_A; |
| pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A; |
| } else if (pmadapter->fw_bands & BAND_GN) { |
| pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; |
| pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; |
| pmadapter->adhoc_11n_enabled = MTRUE; |
| } else if (pmadapter->fw_bands & BAND_G) { |
| pmadapter->adhoc_start_band = BAND_G | BAND_B; |
| pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; |
| } else if (pmadapter->fw_bands & BAND_B) { |
| pmadapter->adhoc_start_band = BAND_B; |
| pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; |
| } |
| |
| pmadapter->fw_release_number = hw_spec->fw_release_number; |
| pmadapter->number_of_antenna = hw_spec->number_of_antenna; |
| |
| PRINTM(MINFO, "GET_HW_SPEC: fw_release_number- 0x%X\n", |
| wlan_le32_to_cpu(pmadapter->fw_release_number)); |
| PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n", |
| hw_spec->permanent_addr[0], hw_spec->permanent_addr[1], |
| hw_spec->permanent_addr[2], hw_spec->permanent_addr[3], |
| hw_spec->permanent_addr[4], hw_spec->permanent_addr[5]); |
| PRINTM(MINFO, "GET_HW_SPEC: hw_if_version=0x%X version=0x%X\n", |
| wlan_le16_to_cpu(hw_spec->hw_if_version), |
| wlan_le16_to_cpu(hw_spec->version)); |
| |
| if (pmpriv->curr_addr[0] == 0xff) |
| memmove(pmpriv->curr_addr, hw_spec->permanent_addr, |
| MLAN_MAC_ADDR_LENGTH); |
| |
| pmadapter->region_code = wlan_le16_to_cpu(hw_spec->region_code); |
| |
| for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { |
| /* Use the region code to search for the index */ |
| if (pmadapter->region_code == region_code_index[i]) |
| break; |
| } |
| |
| /* If it's unidentified region code, use the default (USA) */ |
| if (i >= MRVDRV_MAX_REGION_CODE) { |
| pmadapter->region_code = 0x10; |
| PRINTM(MWARN, "unidentified region code, use the default (USA)\n"); |
| } |
| if (wlan_set_regiontable(pmpriv, (t_u8) pmadapter->region_code, |
| pmadapter->fw_bands)) { |
| ret = MLAN_STATUS_FAILURE; |
| goto done; |
| } |
| |
| if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands)) { |
| ret = MLAN_STATUS_FAILURE; |
| goto done; |
| } |
| |
| pmadapter->hw_dot_11n_dev_cap = wlan_le32_to_cpu(hw_spec->dot_11n_dev_cap); |
| pmadapter->usr_dot_11n_dev_cap = pmadapter->hw_dot_11n_dev_cap & |
| DEFAULT_11N_CAP_MASK; |
| pmadapter->usr_dev_mcs_support = pmadapter->hw_dev_mcs_support = |
| hw_spec->dev_mcs_support; |
| wlan_show_dot11ndevcap(pmadapter, pmadapter->hw_dot_11n_dev_cap); |
| wlan_show_devmcssupport(pmadapter, pmadapter->hw_dev_mcs_support); |
| pmadapter->mp_end_port = wlan_le16_to_cpu(hw_spec->mp_end_port); |
| |
| for (i = 1; i <= (unsigned) (MAX_PORT - pmadapter->mp_end_port); i++) { |
| pmadapter->mp_data_port_mask &= ~(1 << (MAX_PORT - i)); |
| } |
| |
| done: |
| LEAVE(); |
| return ret; |
| } |
| |
| /** |
| * @brief This function handles the command response of RSSI info |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_rssi_info(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_RSSI_INFO_RSP *prssi_info_rsp = |
| &resp->params.rssi_info_rsp; |
| mlan_ds_get_info *pget_info = MNULL; |
| |
| ENTER(); |
| |
| pmpriv->data_rssi_last = wlan_le16_to_cpu(prssi_info_rsp->data_rssi_last); |
| pmpriv->data_nf_last = wlan_le16_to_cpu(prssi_info_rsp->data_nf_last); |
| |
| pmpriv->data_rssi_avg = wlan_le16_to_cpu(prssi_info_rsp->data_rssi_avg); |
| pmpriv->data_nf_avg = wlan_le16_to_cpu(prssi_info_rsp->data_nf_avg); |
| |
| pmpriv->bcn_rssi_last = wlan_le16_to_cpu(prssi_info_rsp->bcn_rssi_last); |
| pmpriv->bcn_nf_last = wlan_le16_to_cpu(prssi_info_rsp->bcn_nf_last); |
| |
| pmpriv->bcn_rssi_avg = wlan_le16_to_cpu(prssi_info_rsp->bcn_rssi_avg); |
| pmpriv->bcn_nf_avg = wlan_le16_to_cpu(prssi_info_rsp->bcn_nf_avg); |
| |
| /* Need to indicate IOCTL complete */ |
| if (pioctl_buf != MNULL) { |
| pget_info = (mlan_ds_get_info *) pioctl_buf->pbuf; |
| |
| memset(pget_info, 0, sizeof(mlan_ds_get_info)); |
| |
| pget_info->param.signal.selector = ALL_RSSI_INFO_MASK; |
| |
| /* RSSI */ |
| pget_info->param.signal.bcn_rssi_last = pmpriv->bcn_rssi_last; |
| pget_info->param.signal.bcn_rssi_avg = pmpriv->bcn_rssi_avg; |
| pget_info->param.signal.data_rssi_last = pmpriv->data_rssi_last; |
| pget_info->param.signal.data_rssi_avg = pmpriv->data_rssi_avg; |
| |
| /* SNR */ |
| pget_info->param.signal.bcn_snr_last = |
| CAL_SNR(pmpriv->bcn_rssi_last, pmpriv->bcn_nf_last); |
| pget_info->param.signal.bcn_snr_avg = |
| CAL_SNR(pmpriv->bcn_rssi_avg, pmpriv->bcn_nf_avg); |
| pget_info->param.signal.data_snr_last = |
| CAL_SNR(pmpriv->data_rssi_last, pmpriv->data_nf_last); |
| pget_info->param.signal.data_snr_avg = |
| CAL_SNR(pmpriv->data_rssi_avg, pmpriv->data_nf_avg); |
| |
| /* NF */ |
| pget_info->param.signal.bcn_nf_last = pmpriv->bcn_nf_last; |
| pget_info->param.signal.bcn_nf_avg = pmpriv->bcn_nf_avg; |
| pget_info->param.signal.data_nf_last = pmpriv->data_nf_last; |
| pget_info->param.signal.data_nf_avg = pmpriv->data_nf_avg; |
| |
| pioctl_buf->data_read_written = sizeof(mlan_ds_get_info); |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of mac_control |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_mac_control(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| ENTER(); |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of snmp_mib |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_snmp_mib(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_SNMP_MIB *psmib = &resp->params.smib; |
| t_u16 oid = wlan_le16_to_cpu(psmib->oid); |
| t_u16 query_type = wlan_le16_to_cpu(psmib->query_type); |
| t_u32 ul_temp; |
| mlan_ds_snmp_mib *mib = MNULL; |
| |
| ENTER(); |
| |
| if (pioctl_buf) |
| mib = (mlan_ds_snmp_mib *) pioctl_buf->pbuf; |
| |
| PRINTM(MINFO, "SNMP_RESP: value of the oid = 0x%x, query_type=0x%x\n", oid, |
| query_type); |
| PRINTM(MINFO, "SNMP_RESP: Buf size = 0x%x\n", |
| wlan_le16_to_cpu(psmib->buf_size)); |
| if (query_type == HostCmd_ACT_GEN_GET) { |
| switch (oid) { |
| case FragThresh_i: |
| ul_temp = wlan_le16_to_cpu(*((t_u16 *) (psmib->value))); |
| PRINTM(MINFO, "SNMP_RESP: FragThsd =%u\n", ul_temp); |
| if (mib) |
| mib->param.frag_threshold = ul_temp; |
| break; |
| |
| case RtsThresh_i: |
| ul_temp = wlan_le16_to_cpu(*((t_u16 *) (psmib->value))); |
| PRINTM(MINFO, "SNMP_RESP: RTSThsd =%u\n", ul_temp); |
| if (mib) |
| mib->param.rts_threshold = ul_temp; |
| break; |
| |
| case ShortRetryLim_i: |
| ul_temp = wlan_le16_to_cpu(*((t_u16 *) (psmib->value))); |
| PRINTM(MINFO, "SNMP_RESP: TxRetryCount=%u\n", ul_temp); |
| if (mib) |
| mib->param.retry_count = ul_temp; |
| break; |
| case WwsMode_i: |
| ul_temp = wlan_le16_to_cpu(*((t_u16 *) (psmib->value))); |
| PRINTM(MINFO, "SNMP_RESP: WWSCfg =%u\n", ul_temp); |
| if (pioctl_buf) |
| ((mlan_ds_misc_cfg *) pioctl_buf->pbuf)->param.wws_cfg = |
| ul_temp; |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| if (pioctl_buf) { |
| /* Indicate ioctl complete */ |
| pioctl_buf->data_read_written = sizeof(mlan_ds_snmp_mib); |
| } |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of get_log |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_get_log(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_GET_LOG *pget_log = |
| (HostCmd_DS_802_11_GET_LOG *) & resp->params.get_log; |
| mlan_ds_get_info *pget_info = MNULL; |
| |
| ENTER(); |
| if (pioctl_buf) { |
| pget_info = (mlan_ds_get_info *) pioctl_buf->pbuf; |
| pget_info->param.stats.mcast_tx_frame = |
| wlan_le32_to_cpu(pget_log->mcast_tx_frame); |
| pget_info->param.stats.failed = wlan_le32_to_cpu(pget_log->failed); |
| pget_info->param.stats.retry = wlan_le32_to_cpu(pget_log->retry); |
| pget_info->param.stats.multi_retry = |
| wlan_le32_to_cpu(pget_log->multiretry); |
| pget_info->param.stats.frame_dup = |
| wlan_le32_to_cpu(pget_log->frame_dup); |
| pget_info->param.stats.rts_success = |
| wlan_le32_to_cpu(pget_log->rts_success); |
| pget_info->param.stats.rts_failure = |
| wlan_le32_to_cpu(pget_log->rts_failure); |
| pget_info->param.stats.ack_failure = |
| wlan_le32_to_cpu(pget_log->ack_failure); |
| pget_info->param.stats.rx_frag = wlan_le32_to_cpu(pget_log->rx_frag); |
| pget_info->param.stats.mcast_rx_frame = |
| wlan_le32_to_cpu(pget_log->mcast_rx_frame); |
| pget_info->param.stats.fcs_error = |
| wlan_le32_to_cpu(pget_log->fcs_error); |
| pget_info->param.stats.tx_frame = wlan_le32_to_cpu(pget_log->tx_frame); |
| pget_info->param.stats.wep_icv_error[0] = |
| wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[0]); |
| pget_info->param.stats.wep_icv_error[1] = |
| wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[1]); |
| pget_info->param.stats.wep_icv_error[2] = |
| wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[2]); |
| pget_info->param.stats.wep_icv_error[3] = |
| wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[3]); |
| /* Indicate ioctl complete */ |
| pioctl_buf->data_read_written = sizeof(mlan_ds_get_info); |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of radio_control |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_radio_control(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_RADIO_CONTROL *pradio_ctrl = |
| (HostCmd_DS_802_11_RADIO_CONTROL *) & resp->params.radio; |
| mlan_ds_radio_cfg *radio_cfg = MNULL; |
| mlan_adapter *pmadapter = pmpriv->adapter; |
| |
| ENTER(); |
| pmadapter->radio_on = wlan_le16_to_cpu(pradio_ctrl->control); |
| if (pioctl_buf) { |
| radio_cfg = (mlan_ds_radio_cfg *) pioctl_buf->pbuf; |
| radio_cfg->param.radio_on_off = (t_u32) pmadapter->radio_on; |
| pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg); |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of tx_rate_cfg |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_adapter *pmadapter = pmpriv->adapter; |
| mlan_ds_rate *ds_rate = MNULL; |
| HostCmd_DS_TX_RATE_CFG *prate_cfg = &resp->params.tx_rate_cfg; |
| MrvlRateScope_t *prate_scope; |
| MrvlIEtypesHeader_t *head = MNULL; |
| t_u16 tlv, tlv_buf_len; |
| t_u8 *tlv_buf; |
| t_u32 i; |
| mlan_status ret = MLAN_STATUS_SUCCESS; |
| |
| ENTER(); |
| |
| tlv_buf = (t_u8 *) ((t_u8 *) prate_cfg) + sizeof(HostCmd_DS_TX_RATE_CFG); |
| tlv_buf_len = *(t_u16 *) (tlv_buf + sizeof(t_u16)); |
| tlv_buf_len = wlan_le16_to_cpu(tlv_buf_len); |
| |
| while (tlv_buf && tlv_buf_len > 0) { |
| tlv = (*tlv_buf); |
| tlv = tlv | (*(tlv_buf + 1) << 8); |
| |
| switch (tlv) { |
| case TLV_TYPE_RATE_SCOPE: |
| prate_scope = (MrvlRateScope_t *) tlv_buf; |
| pmpriv->bitmap_rates[0] = |
| wlan_le16_to_cpu(prate_scope->hr_dsss_rate_bitmap); |
| pmpriv->bitmap_rates[1] = |
| wlan_le16_to_cpu(prate_scope->ofdm_rate_bitmap); |
| for (i = 0; |
| i < sizeof(prate_scope->ht_mcs_rate_bitmap) / sizeof(t_u16); |
| i++) |
| pmpriv->bitmap_rates[2 + i] = |
| wlan_le16_to_cpu(prate_scope->ht_mcs_rate_bitmap[i]); |
| break; |
| /* Add RATE_DROP tlv here */ |
| } |
| |
| head = (MrvlIEtypesHeader_t *) tlv_buf; |
| head->len = wlan_le16_to_cpu(head->len); |
| tlv_buf += head->len + sizeof(MrvlIEtypesHeader_t); |
| tlv_buf_len -= head->len; |
| } |
| |
| pmpriv->is_data_rate_auto = wlan_is_rate_auto(pmpriv); |
| |
| if (pmpriv->is_data_rate_auto) { |
| pmpriv->data_rate = 0; |
| } else { |
| ret = wlan_prepare_cmd(pmpriv, |
| HostCmd_CMD_802_11_TX_RATE_QUERY, |
| HostCmd_ACT_GEN_GET, 0, MNULL, MNULL); |
| |
| } |
| |
| if (pioctl_buf) { |
| ds_rate = (mlan_ds_rate *) pioctl_buf->pbuf; |
| if (wlan_le16_to_cpu(prate_cfg->action) == HostCmd_ACT_GEN_GET) { |
| if (pmpriv->is_data_rate_auto) |
| ds_rate->param.rate_cfg.is_rate_auto = 1; |
| else { |
| ds_rate->param.rate_cfg.rate = |
| wlan_get_rate_index(pmadapter, pmpriv->bitmap_rates, |
| sizeof(pmpriv->bitmap_rates)); |
| if (ds_rate->param.rate_cfg.rate >= MLAN_RATE_BITMAP_OFDM0 && |
| ds_rate->param.rate_cfg.rate <= MLAN_RATE_BITMAP_OFDM7) |
| ds_rate->param.rate_cfg.rate -= |
| (MLAN_RATE_BITMAP_OFDM0 - MLAN_RATE_INDEX_OFDM0); |
| if (ds_rate->param.rate_cfg.rate >= MLAN_RATE_BITMAP_MCS0 && |
| ds_rate->param.rate_cfg.rate <= MLAN_RATE_BITMAP_MCS127) |
| ds_rate->param.rate_cfg.rate -= |
| (MLAN_RATE_BITMAP_MCS0 - MLAN_RATE_INDEX_MCS0); |
| } |
| } |
| } |
| |
| LEAVE(); |
| return ret; |
| } |
| |
| /** |
| * @brief Get power level and rate index |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param pdata_buf Pointer to the data buffer |
| * |
| * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE |
| */ |
| static mlan_status |
| wlan_get_power_level(pmlan_private pmpriv, void *pdata_buf) |
| { |
| int length = -1, max_power = -1, min_power = -1; |
| MrvlTypes_Power_Group_t *ppg_tlv = MNULL; |
| Power_Group_t *pg = MNULL; |
| |
| ENTER(); |
| |
| if (pdata_buf) { |
| ppg_tlv = |
| (MrvlTypes_Power_Group_t *) ((t_u8 *) pdata_buf + |
| sizeof(HostCmd_DS_TXPWR_CFG)); |
| pg = (Power_Group_t *) ((t_u8 *) ppg_tlv + |
| sizeof(MrvlTypes_Power_Group_t)); |
| length = ppg_tlv->length; |
| if (length > 0) { |
| max_power = pg->power_max; |
| min_power = pg->power_min; |
| length -= sizeof(Power_Group_t); |
| } |
| while (length) { |
| pg++; |
| if (max_power < pg->power_max) { |
| max_power = pg->power_max; |
| } |
| if (min_power > pg->power_min) { |
| min_power = pg->power_min; |
| } |
| length -= sizeof(Power_Group_t); |
| } |
| if (ppg_tlv->length > 0) { |
| pmpriv->min_tx_power_level = (t_u8) min_power; |
| pmpriv->max_tx_power_level = (t_u8) max_power; |
| } |
| } else { |
| LEAVE(); |
| return MLAN_STATUS_FAILURE; |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of tx_power_cfg |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_tx_power_cfg(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_adapter *pmadapter = pmpriv->adapter; |
| HostCmd_DS_TXPWR_CFG *ptxp_cfg = &resp->params.txp_cfg; |
| MrvlTypes_Power_Group_t *ppg_tlv = MNULL; |
| Power_Group_t *pg = MNULL; |
| t_u16 action = wlan_le16_to_cpu(ptxp_cfg->action); |
| mlan_ds_power_cfg *power = MNULL; |
| t_u32 data[5]; |
| |
| ENTER(); |
| switch (action) { |
| case HostCmd_ACT_GEN_GET: |
| { |
| ppg_tlv = |
| (MrvlTypes_Power_Group_t *) ((t_u8 *) ptxp_cfg + |
| sizeof(HostCmd_DS_TXPWR_CFG)); |
| pg = (Power_Group_t *) ((t_u8 *) ppg_tlv + |
| sizeof(MrvlTypes_Power_Group_t)); |
| ppg_tlv->length = wlan_le16_to_cpu(ppg_tlv->length); |
| if (pmadapter->hw_status == WlanHardwareStatusInitializing) |
| wlan_get_power_level(pmpriv, ptxp_cfg); |
| pmpriv->tx_power_level = (t_u16) pg->power_min; |
| break; |
| } |
| case HostCmd_ACT_GEN_SET: |
| if (wlan_le32_to_cpu(ptxp_cfg->mode)) { |
| ppg_tlv = |
| (MrvlTypes_Power_Group_t *) ((t_u8 *) ptxp_cfg + |
| sizeof(HostCmd_DS_TXPWR_CFG)); |
| pg = (Power_Group_t *) ((t_u8 *) ppg_tlv + |
| sizeof(MrvlTypes_Power_Group_t)); |
| if (pg->power_max == pg->power_min) |
| pmpriv->tx_power_level = (t_u16) pg->power_min; |
| } |
| break; |
| default: |
| PRINTM(MERROR, "CMD_RESP: unknown command action %d\n", action); |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| PRINTM(MINFO, "Current TxPower Level = %d,Max Power=%d, Min Power=%d\n", |
| pmpriv->tx_power_level, pmpriv->max_tx_power_level, |
| pmpriv->min_tx_power_level); |
| |
| if (pioctl_buf) { |
| power = (mlan_ds_power_cfg *) pioctl_buf->pbuf; |
| if (action == HostCmd_ACT_GEN_GET) { |
| if (power->sub_command == MLAN_OID_POWER_CFG) { |
| pioctl_buf->data_read_written = |
| sizeof(mlan_power_cfg_t) + MLAN_SUB_COMMAND_SIZE; |
| power->param.power_cfg.power_level = pmpriv->tx_power_level; |
| if (wlan_le32_to_cpu(ptxp_cfg->mode)) |
| power->param.power_cfg.is_power_auto = 0; |
| else |
| power->param.power_cfg.is_power_auto = 1; |
| } else { |
| power->param.power_ext.len = 0; |
| while (ppg_tlv->length) { |
| data[0] = pg->first_rate_code; |
| data[1] = pg->last_rate_code; |
| if (pg->modulation_class == MOD_CLASS_OFDM) { |
| data[0] += MLAN_RATE_INDEX_OFDM0; |
| data[1] += MLAN_RATE_INDEX_OFDM0; |
| } else if (pg->modulation_class == MOD_CLASS_HT) { |
| data[0] += MLAN_RATE_INDEX_MCS0; |
| data[1] += MLAN_RATE_INDEX_MCS0; |
| if (pg->ht_bandwidth == HT_BW_40) { |
| data[0] |= TX_RATE_HT_BW40_BIT; |
| data[1] |= TX_RATE_HT_BW40_BIT; |
| } |
| } |
| data[2] = pg->power_min; |
| data[3] = pg->power_max; |
| data[4] = pg->power_step; |
| memcpy((t_u8 *) & power->param.power_ext. |
| power_data[power->param.power_ext.len], |
| (t_u8 *) data, sizeof(data)); |
| power->param.power_ext.len += 5; |
| pg++; |
| ppg_tlv->length -= sizeof(Power_Group_t); |
| } |
| pioctl_buf->data_read_written = |
| sizeof(mlan_power_cfg_ext) + MLAN_SUB_COMMAND_SIZE; |
| } |
| } |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of ps_mode_enh |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_opt_ps_mode(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| pmlan_adapter pmadapter = pmpriv->adapter; |
| HostCmd_DS_802_11_PS_MODE_ENH *pps_mode = &resp->params.psmode_enh; |
| |
| ENTER(); |
| |
| PRINTM(MINFO, "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n", |
| resp->result, pps_mode->action); |
| pps_mode->action = wlan_le16_to_cpu(pps_mode->action); |
| |
| switch (pps_mode->action) { |
| case EN_PS: |
| pmadapter->ps_state = PS_STATE_AWAKE; |
| PRINTM(MDATA, "Settting ps_state to AWAKE\n"); |
| if (pmadapter->sleep_period.period) { |
| PRINTM(MDATA, "Setting uapsd/pps mode to TRUE\n"); |
| } |
| break; |
| case DIS_PS: |
| pmadapter->ps_state = PS_STATE_AWAKE; |
| PRINTM(MDATA, "Setting ps_state to AWAKE\n"); |
| if (pmadapter->sleep_period.period) { |
| pmadapter->delay_null_pkt = MFALSE; |
| pmadapter->tx_lock_flag = MFALSE; |
| } |
| break; |
| case EN_AUTO_DS: |
| pmadapter->ps_state = PS_STATE_AWAKE; |
| PRINTM(MDATA, "Enabled auto deep sleep\n"); |
| pmpriv->adapter->is_deep_sleep = MTRUE; |
| break; |
| case DIS_AUTO_DS: |
| pmpriv->adapter->is_deep_sleep = MFALSE; |
| pmadapter->ps_state = PS_STATE_AWAKE; |
| PRINTM(MDATA, "Disabled auto deep sleep\n"); |
| break; |
| case SLEEP_CONFIRM: |
| PRINTM(MDATA, |
| "Received Sleep confirm response, setting ps_state to SLEEP\n"); |
| pmadapter->ps_state = PS_STATE_SLEEP; |
| break; |
| default: |
| PRINTM(MERROR, "CMD_RESP: unknown PS_MODE action 0x%x\n", |
| pps_mode->action); |
| break; |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of sleep_period |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_sleep_period(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_SLEEP_PERIOD *pcmd_sleep_pd = &resp->params.sleep_pd; |
| mlan_ds_pm_cfg *pm_cfg = MNULL; |
| t_u16 sleep_pd = 0; |
| |
| ENTER(); |
| |
| sleep_pd = wlan_le16_to_cpu(pcmd_sleep_pd->sleep_pd); |
| if (pioctl_buf) { |
| pm_cfg = (mlan_ds_pm_cfg *) pioctl_buf->pbuf; |
| pm_cfg->param.sleep_period = (t_u32) sleep_pd; |
| pioctl_buf->data_read_written = sizeof(pm_cfg->param.sleep_period) |
| + MLAN_SUB_COMMAND_SIZE; |
| } |
| pmpriv->adapter->sleep_period.period = sleep_pd; |
| if (sleep_pd == SLEEP_PERIOD_RESERVED_FF) |
| pmpriv->gen_null_pkg = MFALSE; |
| else |
| pmpriv->gen_null_pkg = MTRUE; |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of sleep_params |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_sleep_params(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_SLEEP_PARAMS *presp_sp = &resp->params.sleep_param; |
| mlan_ds_pm_cfg *pm_cfg = MNULL; |
| mlan_ds_sleep_params *psp = MNULL; |
| sleep_params_t *psleep_params = &pmpriv->adapter->sleep_params; |
| |
| ENTER(); |
| |
| psleep_params->sp_reserved = wlan_le16_to_cpu(presp_sp->reserved); |
| psleep_params->sp_error = wlan_le16_to_cpu(presp_sp->error); |
| psleep_params->sp_offset = wlan_le16_to_cpu(presp_sp->offset); |
| psleep_params->sp_stable_time = wlan_le16_to_cpu(presp_sp->stable_time); |
| psleep_params->sp_cal_control = presp_sp->cal_control; |
| psleep_params->sp_ext_sleep_clk = presp_sp->external_sleep_clk; |
| |
| if (pioctl_buf) { |
| pm_cfg = (mlan_ds_pm_cfg *) pioctl_buf->pbuf; |
| psp = (mlan_ds_sleep_params *) & pm_cfg->param.sleep_params; |
| |
| psp->error = (t_u32) psleep_params->sp_error; |
| psp->offset = (t_u32) psleep_params->sp_offset; |
| psp->stable_time = (t_u32) psleep_params->sp_stable_time; |
| psp->cal_control = (t_u32) psleep_params->sp_cal_control; |
| psp->ext_sleep_clk = (t_u32) psleep_params->sp_ext_sleep_clk; |
| psp->reserved = (t_u32) psleep_params->sp_reserved; |
| |
| pioctl_buf->data_read_written = sizeof(pm_cfg->param.sleep_params) |
| + MLAN_SUB_COMMAND_SIZE; |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of mac_address |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_mac_address(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_MAC_ADDRESS *pmac_addr = &resp->params.mac_addr; |
| mlan_ds_bss *bss = MNULL; |
| |
| ENTER(); |
| |
| memcpy(pmpriv->curr_addr, pmac_addr->mac_addr, MLAN_MAC_ADDR_LENGTH); |
| |
| PRINTM(MINFO, "set mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", |
| pmpriv->curr_addr[0], pmpriv->curr_addr[1], pmpriv->curr_addr[2], |
| pmpriv->curr_addr[3], pmpriv->curr_addr[4], pmpriv->curr_addr[5]); |
| if (pioctl_buf) { |
| bss = (mlan_ds_bss *) pioctl_buf->pbuf; |
| memcpy(&bss->param.mac_addr, pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH); |
| pioctl_buf->data_read_written = |
| MLAN_MAC_ADDR_LENGTH + MLAN_SUB_COMMAND_SIZE; |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of multicast_address |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_mac_multicast_adr(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| ENTER(); |
| if (pioctl_buf) { |
| pioctl_buf->data_read_written = |
| sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE; |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of tx rate query |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_adapter *pmadapter = pmpriv->adapter; |
| mlan_ds_rate *rate = MNULL; |
| ENTER(); |
| |
| pmpriv->tx_rate = resp->params.tx_rate.tx_rate; |
| pmpriv->tx_htinfo = resp->params.tx_rate.ht_info; |
| if (!pmpriv->is_data_rate_auto) { |
| pmpriv->data_rate = |
| wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate, |
| pmpriv->tx_htinfo); |
| } |
| |
| if (pioctl_buf) { |
| rate = (mlan_ds_rate *) pioctl_buf->pbuf; |
| if (rate->sub_command == MLAN_OID_RATE_CFG) { |
| if (rate->param.rate_cfg.rate_type == MLAN_RATE_INDEX) { |
| if (pmpriv->tx_htinfo & MBIT(0)) |
| rate->param.rate_cfg.rate = |
| pmpriv->tx_rate + MLAN_RATE_INDEX_MCS0; |
| else |
| /* For HostCmd_CMD_802_11_TX_RATE_QUERY, there is a hole in |
| rate table between HR/DSSS and OFDM rates, so minus 1 |
| for OFDM rate index */ |
| rate->param.rate_cfg.rate = |
| (pmpriv->tx_rate > |
| MLAN_RATE_INDEX_OFDM0) ? pmpriv->tx_rate - |
| 1 : pmpriv->tx_rate; |
| } else { |
| rate->param.rate_cfg.rate = |
| wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate, |
| pmpriv->tx_htinfo); |
| } |
| } else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) { |
| if (pmpriv->tx_htinfo & MBIT(0)) |
| rate->param.data_rate.tx_data_rate = |
| pmpriv->tx_rate + MLAN_RATE_INDEX_MCS0; |
| else |
| /* For HostCmd_CMD_802_11_TX_RATE_QUERY, there is a hole in |
| rate table between HR/DSSS and OFDM rates, so minus 1 for |
| OFDM rate index */ |
| rate->param.data_rate.tx_data_rate = |
| (pmpriv->tx_rate > |
| MLAN_RATE_INDEX_OFDM0) ? pmpriv->tx_rate - |
| 1 : pmpriv->tx_rate; |
| if (pmpriv->rxpd_htinfo & MBIT(0)) |
| rate->param.data_rate.rx_data_rate = |
| pmpriv->rxpd_rate + MLAN_RATE_INDEX_MCS0; |
| else |
| /* For rate index in RxPD, there is a hole in rate table |
| between HR/DSSS and OFDM rates, so minus 1 for OFDM rate |
| index */ |
| rate->param.data_rate.rx_data_rate = |
| (pmpriv->rxpd_rate > |
| MLAN_RATE_INDEX_OFDM0) ? pmpriv->rxpd_rate - |
| 1 : pmpriv->rxpd_rate; |
| } |
| pioctl_buf->data_read_written = |
| sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE; |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of deauthenticate |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_deauthenticate(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_adapter *pmadapter = pmpriv->adapter; |
| ENTER(); |
| |
| pmadapter->dbg.num_cmd_deauth++; |
| if (!memcmp(resp->params.deauth.mac_addr, |
| &pmpriv->curr_bss_params.bss_descriptor.mac_address, |
| sizeof(resp->params.deauth.mac_addr))) { |
| wlan_reset_connect_state(pmpriv); |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of ad_hoc_stop |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_ad_hoc_stop(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| ENTER(); |
| |
| wlan_reset_connect_state(pmpriv); |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of key_material |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_key_material(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_KEY_MATERIAL *pkey = &resp->params.key_material; |
| |
| ENTER(); |
| |
| if (wlan_le16_to_cpu(pkey->action) == HostCmd_ACT_GEN_SET) { |
| if ((wlan_le16_to_cpu(pkey->key_param_set.key_info) & |
| KEY_INFO_TKIP_MCAST)) { |
| PRINTM(MINFO, "key: GTK is set\n"); |
| pmpriv->wpa_is_gtk_set = MTRUE; |
| |
| } |
| } |
| |
| memset(pmpriv->aes_key.key_param_set.key, 0, |
| sizeof(pkey->key_param_set.key)); |
| pmpriv->aes_key.key_param_set.key_len = |
| wlan_le16_to_cpu(pkey->key_param_set.key_len); |
| memcpy(pmpriv->aes_key.key_param_set.key, pkey->key_param_set.key, |
| pmpriv->aes_key.key_param_set.key_len); |
| |
| HEXDUMP("CMD_RESP (Key_Material)", pmpriv->aes_key.key_param_set.key, |
| pmpriv->aes_key.key_param_set.key_len); |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief Handle the supplicant pmk response |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_supplicant_pmk(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_SUPPLICANT_PMK *supplicant_pmk_resp = |
| &resp->params.esupplicant_psk; |
| mlan_ds_sec_cfg *sec = MNULL; |
| MrvlIEtypes_PMK_t *ppmk_tlv = MNULL; |
| MrvlIEtypes_Passphrase_t *passphrase_tlv = MNULL; |
| MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL; |
| MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL; |
| t_u8 *tlv_buf = (t_u8 *) supplicant_pmk_resp->tlv_buffer; |
| t_u16 action = wlan_le16_to_cpu(supplicant_pmk_resp->action); |
| int tlv_buf_len = 0; |
| t_u16 tlv; |
| |
| ENTER(); |
| tlv_buf_len = resp->size - (sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + |
| S_DS_GEN - 1); |
| if (pioctl_buf) { |
| sec = (mlan_ds_sec_cfg *) pioctl_buf->pbuf; |
| if (action == HostCmd_ACT_GEN_GET) { |
| while (tlv_buf_len > 0) { |
| tlv = (*tlv_buf) | (*(tlv_buf + 1) << 8); |
| if ((tlv != TLV_TYPE_SSID) && (tlv != TLV_TYPE_BSSID) && |
| (tlv != TLV_TYPE_PASSPHRASE) |
| && (tlv != TLV_TYPE_PMK)) |
| break; |
| switch (tlv) { |
| case TLV_TYPE_SSID: |
| pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *) tlv_buf; |
| pssid_tlv->header.len = |
| wlan_le16_to_cpu(pssid_tlv->header.len); |
| memcpy(sec->param.passphrase.ssid.ssid, pssid_tlv->ssid, |
| pssid_tlv->header.len); |
| sec->param.passphrase.ssid.ssid_len = pssid_tlv->header.len; |
| tlv_buf += |
| pssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t); |
| tlv_buf_len -= |
| (pssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t)); |
| break; |
| case TLV_TYPE_BSSID: |
| pbssid_tlv = (MrvlIEtypes_Bssid_t *) tlv_buf; |
| pbssid_tlv->header.len = |
| wlan_le16_to_cpu(pbssid_tlv->header.len); |
| memcpy(&sec->param.passphrase.bssid, pbssid_tlv->bssid, |
| MLAN_MAC_ADDR_LENGTH); |
| tlv_buf += |
| pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t); |
| tlv_buf_len -= |
| (pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t)); |
| break; |
| case TLV_TYPE_PASSPHRASE: |
| passphrase_tlv = (MrvlIEtypes_Passphrase_t *) tlv_buf; |
| passphrase_tlv->header.len = |
| wlan_le16_to_cpu(passphrase_tlv->header.len); |
| sec->param.passphrase.psk_type = MLAN_PSK_PASSPHRASE; |
| sec->param.passphrase.psk.passphrase.passphrase_len = |
| passphrase_tlv->header.len; |
| memcpy(sec->param.passphrase.psk.passphrase.passphrase, |
| passphrase_tlv->passphrase, |
| passphrase_tlv->header.len); |
| tlv_buf += |
| passphrase_tlv->header.len + |
| sizeof(MrvlIEtypesHeader_t); |
| tlv_buf_len -= |
| (passphrase_tlv->header.len + |
| sizeof(MrvlIEtypesHeader_t)); |
| break; |
| case TLV_TYPE_PMK: |
| ppmk_tlv = (MrvlIEtypes_PMK_t *) tlv_buf; |
| ppmk_tlv->header.len = |
| wlan_le16_to_cpu(ppmk_tlv->header.len); |
| sec->param.passphrase.psk_type = MLAN_PSK_PMK; |
| memcpy(sec->param.passphrase.psk.pmk.pmk, ppmk_tlv->pmk, |
| ppmk_tlv->header.len); |
| tlv_buf += |
| ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t); |
| tlv_buf_len -= |
| (ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t)); |
| break; |
| |
| } |
| } |
| } |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief Handle the supplicant profile response |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_supplicant_profile(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_SUPPLICANT_PROFILE *psup_profile = |
| &resp->params.esupplicant_profile; |
| MrvlIEtypesHeader_t *head; |
| MrvlIEtypes_EncrProto_t *encr_proto_tlv = MNULL; |
| MrvlIEtypes_Cipher_t *pcipher_tlv = MNULL; |
| mlan_ds_sec_cfg *sec = MNULL; |
| t_u8 *tlv; |
| int len; |
| |
| ENTER(); |
| |
| len = resp->size - S_DS_GEN - sizeof(t_u16); |
| tlv = psup_profile->tlv_buf; |
| if (pioctl_buf) { |
| sec = (mlan_ds_sec_cfg *) pioctl_buf->pbuf; |
| while (len > 0) { |
| head = (MrvlIEtypesHeader_t *) tlv; |
| head->type = wlan_le16_to_cpu(head->type); |
| head->len = wlan_le16_to_cpu(head->len); |
| switch (head->type) { |
| case TLV_TYPE_ENCRYPTION_PROTO: |
| encr_proto_tlv = (MrvlIEtypes_EncrProto_t *) head; |
| sec->param.esupp_mode.rsn_mode = |
| wlan_le16_to_cpu(encr_proto_tlv->rsn_mode); |
| PRINTM(MCMND, "rsn_mode=0x%x\n", |
| sec->param.esupp_mode.rsn_mode); |
| break; |
| case TLV_TYPE_CIPHER: |
| pcipher_tlv = (MrvlIEtypes_Cipher_t *) head; |
| sec->param.esupp_mode.act_paircipher = pcipher_tlv->pair_cipher; |
| sec->param.esupp_mode.act_groupcipher = |
| pcipher_tlv->group_cipher; |
| PRINTM(MCMND, "paircipher=0x%x, groupcipher=0x%x\n", |
| sec->param.esupp_mode.act_paircipher, |
| sec->param.esupp_mode.act_groupcipher); |
| break; |
| } |
| len -= (head->len - sizeof(MrvlIEtypesHeader_t)); |
| tlv = tlv + (head->len + sizeof(MrvlIEtypesHeader_t)); |
| } |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of rf_channel |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_rf_channel(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_RF_CHANNEL *prf_channel = &resp->params.rf_channel; |
| t_u16 new_channel = wlan_le16_to_cpu(prf_channel->current_channel); |
| mlan_ds_bss *bss = MNULL; |
| ENTER(); |
| if (pmpriv->curr_bss_params.bss_descriptor.channel != new_channel) { |
| PRINTM(MCMND, "Channel Switch: %d to %d\n", |
| pmpriv->curr_bss_params.bss_descriptor.channel, new_channel); |
| /* Update the channel again */ |
| pmpriv->curr_bss_params.bss_descriptor.channel = new_channel; |
| } |
| if (pioctl_buf) { |
| bss = (mlan_ds_bss *) pioctl_buf->pbuf; |
| bss->param.bss_chan.channel = new_channel; |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of rf_antenna |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_802_11_rf_antenna(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_RF_ANTENNA *pantenna = &resp->params.antenna; |
| t_u16 ant_mode = wlan_le16_to_cpu(pantenna->antenna_mode); |
| mlan_ds_radio_cfg *radio = MNULL; |
| |
| ENTER(); |
| |
| PRINTM(MINFO, "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n", |
| wlan_le16_to_cpu(pantenna->action), ant_mode); |
| |
| if (pioctl_buf) { |
| radio = (mlan_ds_radio_cfg *) pioctl_buf->pbuf; |
| radio->param.antenna = ant_mode; |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief Handle the version_ext resp |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_ver_ext(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_VERSION_EXT *ver_ext = &resp->params.verext; |
| mlan_ds_get_info *info; |
| ENTER(); |
| if (pioctl_buf) { |
| info = (mlan_ds_get_info *) pioctl_buf->pbuf; |
| info->param.ver_ext.version_str_sel = ver_ext->version_str_sel; |
| memcpy(info->param.ver_ext.version_str, ver_ext->version_str, |
| sizeof(char) * 128); |
| } |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief Handle the ibss_coalescing_status resp |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_ibss_coalescing_status(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp) |
| { |
| HostCmd_DS_802_11_IBSS_STATUS *pibss_coal_resp = |
| &(resp->params.ibss_coalescing); |
| t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 }; |
| |
| ENTER(); |
| |
| if (wlan_le16_to_cpu(pibss_coal_resp->action) == HostCmd_ACT_GEN_SET) { |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| PRINTM(MINFO, "New BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", |
| pibss_coal_resp->bssid[0], pibss_coal_resp->bssid[1], |
| pibss_coal_resp->bssid[2], pibss_coal_resp->bssid[3], |
| pibss_coal_resp->bssid[4], pibss_coal_resp->bssid[5]); |
| |
| /* If rsp has MNULL BSSID, Just return..... No Action */ |
| if (!memcmp(pibss_coal_resp->bssid, zero_mac, MLAN_MAC_ADDR_LENGTH)) { |
| PRINTM(MMSG, "New BSSID is MNULL\n"); |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /* If BSSID is diff, modify current BSS parameters */ |
| if (memcmp(pmpriv->curr_bss_params.bss_descriptor.mac_address, |
| pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH)) { |
| /* BSSID */ |
| memcpy(pmpriv->curr_bss_params.bss_descriptor.mac_address, |
| pibss_coal_resp->bssid, MLAN_MAC_ADDR_LENGTH); |
| |
| /* Beacon Interval and ATIM window */ |
| pmpriv->curr_bss_params.bss_descriptor.beacon_period |
| = wlan_le16_to_cpu(pibss_coal_resp->beacon_interval); |
| pmpriv->curr_bss_params.bss_descriptor.atim_window |
| = wlan_le16_to_cpu(pibss_coal_resp->atim_window); |
| |
| /* ERP Information */ |
| pmpriv->curr_bss_params.bss_descriptor.erp_flags |
| = (t_u8) wlan_le16_to_cpu(pibss_coal_resp->use_g_rate_protect); |
| |
| pmpriv->adhoc_state = ADHOC_COALESCED; |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| #ifdef MFG_CMD_SUPPORT |
| /** |
| * @brief This function handles the command response of mfg_cmd |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_mfg_cmd(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_ds_misc_cfg *misc; |
| |
| ENTER(); |
| |
| PRINTM(MINFO, "MFG command response size = %d\n", resp->size); |
| resp->size = MIN(resp->size, MRVDRV_SIZE_OF_CMD_BUFFER); |
| if (pioctl_buf) { |
| misc = (mlan_ds_misc_cfg *) pioctl_buf->pbuf; |
| misc->param.mfgcmd.len = resp->size; |
| memcpy(misc->param.mfgcmd.cmd, (void *) resp, resp->size); |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| #endif /* MFG_CMD_SUPPORT */ |
| |
| /** |
| * @brief This function handles the command response of ldo_cfg |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_ldo_cfg(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_ds_misc_cfg *mis_ccfg = MNULL; |
| HostCmd_DS_802_11_LDO_CFG *pldo_cfg = &resp->params.ldo_cfg; |
| |
| ENTER(); |
| |
| if (pioctl_buf) { |
| mis_ccfg = (mlan_ds_misc_cfg *) pioctl_buf->pbuf; |
| mis_ccfg->param.ldo_cfg = wlan_le16_to_cpu(pldo_cfg->pmsource); |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of sysclock |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to mlan_ioctl_req structure |
| * |
| * @return MLAN_STATUS_SUCCESS |
| */ |
| static mlan_status |
| wlan_ret_sysclock_cfg(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_ds_misc_cfg *mis_ccfg = MNULL; |
| HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG *clk_cfg = &resp->params.sys_clock_cfg; |
| int i = 0; |
| |
| ENTER(); |
| |
| if (pioctl_buf) { |
| mis_ccfg = (mlan_ds_misc_cfg *) pioctl_buf->pbuf; |
| mis_ccfg->param.sys_clock.cur_sys_clk = |
| wlan_le16_to_cpu(clk_cfg->cur_sys_clk); |
| mis_ccfg->param.sys_clock.sys_clk_type = |
| wlan_le16_to_cpu(clk_cfg->sys_clk_type); |
| mis_ccfg->param.sys_clock.sys_clk_num = |
| wlan_le16_to_cpu(clk_cfg->sys_clk_len) / sizeof(t_u16); |
| for (i = 0; i < mis_ccfg->param.sys_clock.sys_clk_num; i++) |
| mis_ccfg->param.sys_clock.sys_clk[i] = |
| wlan_le16_to_cpu(clk_cfg->sys_clk[i]); |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of reg_access |
| * |
| * @param type The type of reg access (MAC, BBP or RF) |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to command buffer |
| * |
| * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE |
| */ |
| static mlan_status |
| wlan_ret_reg_access(t_u16 type, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_ds_reg_mem *reg_mem = MNULL; |
| mlan_ds_reg_rw *reg_rw = MNULL; |
| |
| ENTER(); |
| |
| if (pioctl_buf) { |
| reg_mem = (mlan_ds_reg_mem *) pioctl_buf->pbuf; |
| reg_rw = ®_mem->param.reg_rw; |
| switch (type) { |
| case HostCmd_CMD_MAC_REG_ACCESS: |
| { |
| HostCmd_DS_MAC_REG_ACCESS *reg; |
| reg = (HostCmd_DS_MAC_REG_ACCESS *) & resp->params.mac_reg; |
| reg_rw->offset = (t_u32) wlan_le16_to_cpu(reg->offset); |
| reg_rw->value = wlan_le32_to_cpu(reg->value); |
| break; |
| } |
| case HostCmd_CMD_BBP_REG_ACCESS: |
| { |
| HostCmd_DS_BBP_REG_ACCESS *reg; |
| reg = (HostCmd_DS_BBP_REG_ACCESS *) & resp->params.bbp_reg; |
| reg_rw->offset = (t_u32) wlan_le16_to_cpu(reg->offset); |
| reg_rw->value = (t_u32) reg->value; |
| break; |
| } |
| |
| case HostCmd_CMD_RF_REG_ACCESS: |
| { |
| HostCmd_DS_RF_REG_ACCESS *reg; |
| reg = (HostCmd_DS_RF_REG_ACCESS *) & resp->params.rf_reg; |
| reg_rw->offset = (t_u32) wlan_le16_to_cpu(reg->offset); |
| reg_rw->value = (t_u32) reg->value; |
| break; |
| } |
| case HostCmd_CMD_PMIC_REG_ACCESS: |
| { |
| HostCmd_DS_PMIC_REG_ACCESS *reg; |
| reg = (HostCmd_DS_PMIC_REG_ACCESS *) & resp->params.pmic_reg; |
| reg_rw->offset = (t_u32) wlan_le16_to_cpu(reg->offset); |
| reg_rw->value = (t_u32) reg->value; |
| break; |
| } |
| case HostCmd_CMD_CAU_REG_ACCESS: |
| { |
| HostCmd_DS_RF_REG_ACCESS *reg; |
| reg = (HostCmd_DS_RF_REG_ACCESS *) & resp->params.rf_reg; |
| reg_rw->offset = (t_u32) wlan_le16_to_cpu(reg->offset); |
| reg_rw->value = (t_u32) reg->value; |
| break; |
| } |
| case HostCmd_CMD_802_11_EEPROM_ACCESS: |
| { |
| mlan_ds_read_eeprom *eeprom = ®_mem->param.rd_eeprom; |
| HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom = |
| (HostCmd_DS_802_11_EEPROM_ACCESS *) & resp->params.eeprom; |
| cmd_eeprom->byte_count = |
| wlan_le16_to_cpu(cmd_eeprom->byte_count); |
| PRINTM(MINFO, "EEPROM read len=%x\n", cmd_eeprom->byte_count); |
| if (eeprom->byte_count < cmd_eeprom->byte_count) { |
| eeprom->byte_count = 0; |
| PRINTM(MINFO, "EEPROM read return length is too big\n"); |
| LEAVE(); |
| return MLAN_STATUS_FAILURE; |
| } |
| eeprom->offset = wlan_le16_to_cpu(cmd_eeprom->offset); |
| eeprom->byte_count = cmd_eeprom->byte_count; |
| if (eeprom->byte_count > 0) { |
| memcpy(&eeprom->value, &cmd_eeprom->value, |
| eeprom->byte_count); |
| HEXDUMP("EEPROM", (char *) &eeprom->value, |
| eeprom->byte_count); |
| } |
| break; |
| } |
| default: |
| LEAVE(); |
| return MLAN_STATUS_FAILURE; |
| } |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of mem_access |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to command buffer |
| * |
| * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE |
| */ |
| static mlan_status |
| wlan_ret_mem_access(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_ds_reg_mem *reg_mem = MNULL; |
| mlan_ds_mem_rw *mem_rw = MNULL; |
| HostCmd_DS_MEM_ACCESS *mem = (HostCmd_DS_MEM_ACCESS *) & resp->params.mem; |
| |
| ENTER(); |
| |
| if (pioctl_buf) { |
| reg_mem = (mlan_ds_reg_mem *) pioctl_buf->pbuf; |
| mem_rw = ®_mem->param.mem_rw; |
| |
| mem_rw->addr = wlan_le32_to_cpu(mem->addr); |
| mem_rw->value = wlan_le32_to_cpu(mem->value); |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of inactivity timeout |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to command buffer |
| * |
| * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE |
| */ |
| static mlan_status |
| wlan_ret_inactivity_timeout(IN pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| mlan_ds_pm_cfg *pmcfg = MNULL; |
| mlan_ds_inactivity_to *inac_to = MNULL; |
| HostCmd_DS_INACTIVITY_TIMEOUT_EXT *cmd_inac_to = |
| (HostCmd_DS_INACTIVITY_TIMEOUT_EXT *) & resp->params.inactivity_to; |
| |
| ENTER(); |
| |
| if (pioctl_buf) { |
| pmcfg = (mlan_ds_pm_cfg *) pioctl_buf->pbuf; |
| inac_to = &pmcfg->param.inactivity_to; |
| inac_to->timeout_unit = wlan_le16_to_cpu(cmd_inac_to->timeout_unit); |
| inac_to->unicast_timeout = |
| wlan_le16_to_cpu(cmd_inac_to->unicast_timeout); |
| inac_to->mcast_timeout = wlan_le16_to_cpu(cmd_inac_to->mcast_timeout); |
| inac_to->ps_entry_timeout = |
| wlan_le16_to_cpu(cmd_inac_to->ps_entry_timeout); |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /** |
| * @brief This function handles the command response of bca_timeshare |
| * |
| * @param pmpriv A pointer to mlan_private structure |
| * @param resp A pointer to HostCmd_DS_COMMAND |
| * @param pioctl_buf A pointer to command buffer |
| * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE |
| */ |
| static mlan_status |
| wlan_ret_802_11_bca_timeshare(pmlan_private pmpriv, |
| IN HostCmd_DS_COMMAND * resp, |
| IN mlan_ioctl_req * pioctl_buf) |
| { |
| HostCmd_DS_802_11_BCA_TIMESHARE *bca_ts = &resp->params.bca_timeshare; |
| mlan_ds_bca_cfg *bca_cfg = MNULL; |
| |
| ENTER(); |
| |
| PRINTM(MINFO, "TrafficType=0x%x TimeShareInterva=0x%x BTTime=0x%x\n", |
| wlan_le16_to_cpu(bca_ts->traffic_type), |
| wlan_le32_to_cpu(bca_ts->timeshare_interval), |
| wlan_le32_to_cpu(bca_ts->bt_time)); |
| if (pioctl_buf) { |
| bca_cfg = (mlan_ds_bca_cfg *) pioctl_buf->pbuf; |
| bca_cfg->param.bca_ts.traffic_type = |
| wlan_le16_to_cpu(bca_ts->traffic_type); |
| bca_cfg->param.bca_ts.timeshare_interval = |
| wlan_le32_to_cpu(bca_ts->timeshare_interval); |
| bca_cfg->param.bca_ts.bt_time = wlan_le32_to_cpu(bca_ts->bt_time); |
| } |
| |
| LEAVE(); |
| return MLAN_STATUS_SUCCESS; |
| } |
| |
| /******************************************************** |
| Global Functions |
| ********************************************************/ |
| /** |
| * @brief This function handles the station command response |
| * |
| * @param priv A pointer to mlan_private structure |
| * @param cmdresp_no cmd no |
| * @param pcmd_buf cmdresp buf |
| * @param pioctl A pointer to ioctl buf |
| * |
| * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE |
| */ |
| mlan_status |
| mlan_process_sta_cmdresp(IN t_void * priv, |
| IN t_u16 cmdresp_no, |
| IN t_void * pcmd_buf, IN t_void * pioctl) |
| { |
| mlan_status ret = MLAN_STATUS_SUCCESS; |
| mlan_private *pmpriv = (mlan_private *) priv; |
| HostCmd_DS_COMMAND *resp = (HostCmd_DS_COMMAND *) pcmd_buf; |
| mlan_ioctl_req *pioctl_buf = (mlan_ioctl_req *) pioctl; |
| mlan_adapter *pmadapter = pmpriv->adapter; |
| int ctr; |
| /* If the command is not successful, cleanup and return failure */ |
| if ((resp->result != HostCmd_RESULT_OK) |
| ) { |
| wlan_process_cmdresp_error(pmpriv, resp, pioctl_buf); |
| return MLAN_STATUS_FAILURE; |
| } |
| /* Command successful, handle response */ |
| switch (cmdresp_no) { |
| case HostCmd_CMD_GET_HW_SPEC: |
| ret = wlan_ret_get_hw_spec(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_MAC_CONTROL: |
| ret = wlan_ret_mac_control(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_MAC_ADDRESS: |
| ret = wlan_ret_802_11_mac_address(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_MAC_MULTICAST_ADR: |
| ret = wlan_ret_mac_multicast_adr(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_TX_RATE_CFG: |
| ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_SCAN: |
| ret = wlan_ret_802_11_scan(pmpriv, resp, pioctl_buf); |
| pioctl_buf = MNULL; |
| pmadapter->curr_cmd->pioctl_buf = MNULL; |
| break; |
| case HostCmd_CMD_802_11_BG_SCAN_QUERY: |
| ret = wlan_ret_802_11_scan(pmpriv, resp, pioctl_buf); |
| wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN, MNULL); |
| PRINTM(MINFO, "CMD_RESP: BG_SCAN result is ready!\n"); |
| break; |
| case HostCmd_CMD_TXPWR_CFG: |
| ret = wlan_ret_tx_power_cfg(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_PS_MODE_ENH: |
| ret = wlan_ret_802_11_opt_ps_mode(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_HS_CFG_ENH: |
| ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_SLEEP_PERIOD: |
| ret = wlan_ret_802_11_sleep_period(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_SLEEP_PARAMS: |
| ret = wlan_ret_802_11_sleep_params(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_ASSOCIATE: |
| ret = wlan_ret_802_11_associate(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_DEAUTHENTICATE: |
| ret = wlan_ret_802_11_deauthenticate(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_AD_HOC_START: |
| case HostCmd_CMD_802_11_AD_HOC_JOIN: |
| ret = wlan_ret_802_11_ad_hoc(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_AD_HOC_STOP: |
| ret = wlan_ret_802_11_ad_hoc_stop(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_GET_LOG: |
| ret = wlan_ret_get_log(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_RSSI_INFO: |
| ret = wlan_ret_802_11_rssi_info(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_SNMP_MIB: |
| ret = wlan_ret_802_11_snmp_mib(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_RADIO_CONTROL: |
| ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_TX_RATE_QUERY: |
| ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_RF_CHANNEL: |
| ret = wlan_ret_802_11_rf_channel(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_RF_ANTENNA: |
| ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_VERSION_EXT: |
| ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_FUNC_INIT: |
| case HostCmd_CMD_FUNC_SHUTDOWN: |
| break; |
| case HostCmd_CMD_802_11_KEY_MATERIAL: |
| ret = wlan_ret_802_11_key_material(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_SUPPLICANT_PMK: |
| ret = wlan_ret_802_11_supplicant_pmk(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_SUPPLICANT_PROFILE: |
| ret = wlan_ret_802_11_supplicant_profile(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11D_DOMAIN_INFO: |
| ret = wlan_ret_802_11d_domain_info(pmpriv, resp); |
| break; |
| case HostCmd_CMD_802_11_TPC_ADAPT_REQ: |
| case HostCmd_CMD_802_11_TPC_INFO: |
| case HostCmd_CMD_802_11_CHAN_SW_ANN: |
| ret = wlan_11h_cmdresp_process(pmpriv, resp); |
| break; |
| case HostCmd_CMD_11N_ADDBA_REQ: |
| ret = wlan_ret_11n_addba_req(pmpriv, resp); |
| break; |
| case HostCmd_CMD_11N_DELBA: |
| ret = wlan_ret_11n_delba(pmpriv, resp); |
| break; |
| case HostCmd_CMD_11N_ADDBA_RSP: |
| ret = wlan_ret_11n_addba_resp(pmpriv, resp); |
| break; |
| case HostCmd_CMD_RECONFIGURE_TX_BUFF: |
| pmadapter->tx_buf_size = (t_u16) wlan_le16_to_cpu(resp->params. |
| tx_buf.buff_size); |
| pmadapter->mp_end_port = wlan_le16_to_cpu(resp->params. |
| tx_buf.mp_end_port); |
| pmadapter->mp_data_port_mask = DATA_PORT_MASK; |
| |
| for (ctr = 1; ctr <= MAX_PORT - pmadapter->mp_end_port; ctr++) { |
| pmadapter->mp_data_port_mask &= ~(1 << (MAX_PORT - ctr)); |
| } |
| |
| pmadapter->curr_wr_port = 1; |
| PRINTM(MCMND, "end port %d, data port mask %x\n", |
| wlan_le16_to_cpu(resp->params.tx_buf.mp_end_port), |
| pmadapter->mp_data_port_mask); |
| PRINTM(MCMND, "max_tx_buf_size=%d, tx_buf_size=%d\n", |
| pmadapter->max_tx_buf_size, pmadapter->tx_buf_size); |
| break; |
| case HostCmd_CMD_AMSDU_AGGR_CTRL: |
| ret = wlan_ret_amsdu_aggr_ctrl(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_WMM_GET_STATUS: |
| ret = wlan_ret_wmm_get_status(pmpriv, resp); |
| break; |
| case HostCmd_CMD_WMM_ADDTS_REQ: |
| ret = wlan_ret_wmm_addts_req(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_WMM_DELTS_REQ: |
| ret = wlan_ret_wmm_delts_req(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_WMM_QUEUE_CONFIG: |
| ret = wlan_ret_wmm_queue_config(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_WMM_QUEUE_STATS: |
| ret = wlan_ret_wmm_queue_stats(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_WMM_TS_STATUS: |
| ret = wlan_ret_wmm_ts_status(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: |
| ret = wlan_ret_ibss_coalescing_status(pmpriv, resp); |
| break; |
| #ifdef MFG_CMD_SUPPORT |
| case HostCmd_CMD_MFG_COMMAND: |
| ret = wlan_ret_mfg_cmd(pmpriv, resp, pioctl_buf); |
| break; |
| #endif |
| case HostCmd_CMD_11N_CFG: |
| ret = wlan_ret_11n_cfg(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_LDO_CONFIG: |
| ret = wlan_ret_ldo_cfg(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG: |
| ret = wlan_ret_sysclock_cfg(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_MAC_REG_ACCESS: |
| case HostCmd_CMD_BBP_REG_ACCESS: |
| case HostCmd_CMD_RF_REG_ACCESS: |
| case HostCmd_CMD_PMIC_REG_ACCESS: |
| case HostCmd_CMD_CAU_REG_ACCESS: |
| case HostCmd_CMD_802_11_EEPROM_ACCESS: |
| ret = wlan_ret_reg_access(cmdresp_no, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_MEM_ACCESS: |
| ret = wlan_ret_mem_access(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_INACTIVITY_TIMEOUT_EXT: |
| ret = wlan_ret_inactivity_timeout(pmpriv, resp, pioctl_buf); |
| break; |
| case HostCmd_CMD_802_11_BCA_CONFIG_TIMESHARE: |
| ret = wlan_ret_802_11_bca_timeshare(pmpriv, resp, pioctl_buf); |
| break; |
| default: |
| PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n", |
| resp->command); |
| break; |
| } |
| return ret; |
| } |