/** * @brief This function handles the command response of * a block ack response * * @param priv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_ret_11n_addba_resp(mlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp = (HostCmd_DS_11N_ADDBA_RSP *) & resp->params.add_ba_rsp; int tid; RxReorderTbl *rx_reor_tbl_ptr = MNULL; ENTER(); padd_ba_rsp->status_code = wlan_le16_to_cpu(padd_ba_rsp->status_code); padd_ba_rsp->block_ack_param_set = wlan_le16_to_cpu(padd_ba_rsp->block_ack_param_set); padd_ba_rsp->block_ack_tmo = wlan_le16_to_cpu(padd_ba_rsp->block_ack_tmo); padd_ba_rsp->ssn = wlan_le16_to_cpu(padd_ba_rsp->ssn); tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >> BLOCKACKPARAM_TID_POS; /* Check if we had rejected the ADDBA, if yes then do not create the stream */ if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) { PRINTM(MCMND, "ADDBA RSP: %02x:%02x:%02x:%02x:%02x:%02x tid=%d ssn=%d win_size=%d\n", padd_ba_rsp->peer_mac_addr[0], padd_ba_rsp->peer_mac_addr[1], padd_ba_rsp->peer_mac_addr[2], padd_ba_rsp->peer_mac_addr[3], padd_ba_rsp->peer_mac_addr[4], padd_ba_rsp->peer_mac_addr[5], tid, padd_ba_rsp->ssn, ((padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_WINSIZE_MASK) >> BLOCKACKPARAM_WINSIZE_POS)); } else {
/** * @brief This function handles the command response of * a block ack response * * @param priv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_ret_11n_addba_resp(mlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp = (HostCmd_DS_11N_ADDBA_RSP *) & resp->params.add_ba_rsp; int tid, win_size; ENTER(); padd_ba_rsp->status_code = wlan_le16_to_cpu(padd_ba_rsp->status_code); padd_ba_rsp->block_ack_param_set = wlan_le16_to_cpu(padd_ba_rsp->block_ack_param_set); padd_ba_rsp->block_ack_tmo = wlan_le16_to_cpu(padd_ba_rsp->block_ack_tmo); padd_ba_rsp->ssn = wlan_le16_to_cpu(padd_ba_rsp->ssn); tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >> BLOCKACKPARAM_TID_POS; win_size = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_WINSIZE_MASK) >> BLOCKACKPARAM_WINSIZE_POS; wlan_11n_create_rxreorder_tbl(priv, padd_ba_rsp->peer_mac_addr, tid, win_size, padd_ba_rsp->ssn); PRINTM(MEVENT, "ADDBA: %02x:%02x:%02x:%02x:%02x:%02x tid=%d\n", padd_ba_rsp->peer_mac_addr[0], padd_ba_rsp->peer_mac_addr[1], padd_ba_rsp->peer_mac_addr[2], padd_ba_rsp->peer_mac_addr[3], padd_ba_rsp->peer_mac_addr[4], padd_ba_rsp->peer_mac_addr[5], tid); LEAVE(); return MLAN_STATUS_SUCCESS; }
static int wlan_ret_802_11_snmp_mib(WlanCard *cardinfo, HostCmd_DS_COMMAND * resp) { WlanCard *card = cardinfo; HostCmd_DS_802_11_SNMP_MIB *smib = &resp->params.smib; u16 OID = wlan_le16_to_cpu(smib->OID); u16 QueryType = wlan_le16_to_cpu(smib->QueryType); WlanDebug(WlanMsg, "SNMP_RESP: value of the OID = %x, QueryType=%x\n", OID, QueryType); if (QueryType == HostCmd_ACT_GEN_GET) { switch (OID) { case FragThresh_i: card->FragThsd = (*((u16*) (smib->Value))); WlanDebug(WlanEncy,"SNMP_RESP: FragThsd =%u\n",card->FragThsd); break; case RtsThresh_i: card->RTSThsd = (*((u16*) (smib->Value))); WlanDebug(WlanEncy,"SNMP_RESP: RTSThsd =%u\n", card->RTSThsd); break; case ShortRetryLim_i: card->TxRetryCount = (*((u16*) (smib->Value))); WlanDebug(WlanEncy,"SNMP_RESP: TxRetryCount =%u\n",card->TxRetryCount); break; default: break; } } return WLAN_STATUS_SUCCESS; }
/** * @brief This function implements command CMD_802_11D_DOMAIN_INFO * * @param pmpriv A pointer to mlan_private structure * @param pcmd A pointer to HostCmd_DS_COMMAND structure of * command buffer * @param cmd_action Command action * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_cmd_802_11d_domain_info(mlan_private * pmpriv, HostCmd_DS_COMMAND * pcmd, t_u16 cmd_action) { mlan_adapter *pmadapter = pmpriv->adapter; HostCmd_DS_802_11D_DOMAIN_INFO *pdomain_info = &pcmd->params.domain_info; MrvlIEtypes_DomainParamSet_t *domain = &pdomain_info->domain; t_u8 no_of_sub_band = pmadapter->domain_reg.no_of_sub_band; ENTER(); PRINTM(MINFO, "11D: number of sub-band=0x%x\n", no_of_sub_band); pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO); pdomain_info->action = wlan_cpu_to_le16(cmd_action); if (cmd_action == HostCmd_ACT_GEN_GET) { /* Dump domain info */ pcmd->size = wlan_cpu_to_le16(sizeof(pdomain_info->action) + S_DS_GEN); HEXDUMP("11D: 802_11D_DOMAIN_INFO", (t_u8 *) pcmd, wlan_le16_to_cpu(pcmd->size)); LEAVE(); return MLAN_STATUS_SUCCESS; } /* Set domain info fields */ domain->header.type = wlan_cpu_to_le16(TLV_TYPE_DOMAIN); memcpy(pmadapter, domain->country_code, pmadapter->domain_reg.country_code, sizeof(domain->country_code)); domain->header.len = ((no_of_sub_band * sizeof(IEEEtypes_SubbandSet_t)) + sizeof(domain->country_code)); if (no_of_sub_band) { memcpy(pmadapter, domain->sub_band, pmadapter->domain_reg.sub_band, MIN(MRVDRV_MAX_SUBBAND_802_11D, no_of_sub_band) * sizeof(IEEEtypes_SubbandSet_t)); pcmd->size = wlan_cpu_to_le16(sizeof(pdomain_info->action) + domain->header.len + sizeof(MrvlIEtypesHeader_t) + S_DS_GEN); } else { pcmd->size = wlan_cpu_to_le16(sizeof(pdomain_info->action) + S_DS_GEN); } domain->header.len = wlan_cpu_to_le16(domain->header.len); HEXDUMP("11D: 802_11D_DOMAIN_INFO", (t_u8 *) pcmd, wlan_le16_to_cpu(pcmd->size)); LEAVE(); return MLAN_STATUS_SUCCESS; }
static int wlan_ret_802_11_rssi(WlanCard *cardinfo, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_RSSI_RSP *rssirsp = &resp->params.rssirsp; WlanCard *card = cardinfo; rt_kprintf("snr: %d, noise: %d\n", wlan_le16_to_cpu(rssirsp->SNR), wlan_le16_to_cpu(rssirsp->NoiseFloor)); rt_kprintf("avg snr: %d, avg noise: %d\n", wlan_le16_to_cpu(rssirsp->AvgSNR), wlan_le16_to_cpu(rssirsp->AvgNoiseFloor)); return WLAN_STATUS_SUCCESS; }
/** * @brief This function prepares command for adding a block ack * response. * * @param priv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param pdata_buf A pointer to data buffer * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_cmd_11n_addba_rspgen(mlan_private * priv, HostCmd_DS_COMMAND * cmd, void *pdata_buf) { HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp = (HostCmd_DS_11N_ADDBA_RSP *) & cmd->params.add_ba_rsp; HostCmd_DS_11N_ADDBA_REQ *pevt_addba_req = (HostCmd_DS_11N_ADDBA_REQ *) pdata_buf; t_u8 tid = 0; int win_size = 0; ENTER(); pevt_addba_req->block_ack_param_set = wlan_le16_to_cpu(pevt_addba_req->block_ack_param_set); pevt_addba_req->block_ack_tmo = wlan_le16_to_cpu(pevt_addba_req->block_ack_tmo); pevt_addba_req->ssn = wlan_le16_to_cpu(pevt_addba_req->ssn); cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_ADDBA_RSP) + S_DS_GEN); memcpy(priv->adapter, padd_ba_rsp->peer_mac_addr, pevt_addba_req->peer_mac_addr, MLAN_MAC_ADDR_LENGTH); padd_ba_rsp->dialog_token = pevt_addba_req->dialog_token; padd_ba_rsp->block_ack_tmo = wlan_cpu_to_le16(pevt_addba_req->block_ack_tmo); padd_ba_rsp->ssn = wlan_cpu_to_le16(pevt_addba_req->ssn); padd_ba_rsp->block_ack_param_set = pevt_addba_req->block_ack_param_set; tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >> BLOCKACKPARAM_TID_POS; if (priv->addba_reject[tid]) padd_ba_rsp->status_code = wlan_cpu_to_le16(ADDBA_RSP_STATUS_DECLINED); else padd_ba_rsp->status_code = wlan_cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); padd_ba_rsp->block_ack_param_set &= ~BLOCKACKPARAM_WINSIZE_MASK; /* We donot support AMSDU inside AMPDU, hence reset the bit */ padd_ba_rsp->block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; padd_ba_rsp->block_ack_param_set |= (priv->add_ba_param.rx_win_size << BLOCKACKPARAM_WINSIZE_POS); win_size = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_WINSIZE_MASK) >> BLOCKACKPARAM_WINSIZE_POS; padd_ba_rsp->block_ack_param_set = wlan_cpu_to_le16(padd_ba_rsp->block_ack_param_set); wlan_11n_create_rxreorder_tbl(priv, pevt_addba_req->peer_mac_addr, tid, win_size, pevt_addba_req->ssn); LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief This function queues the command to cmd list. * * @param pmadapter A pointer to mlan_adapter structure * @param pcmd_node A pointer to cmd_ctrl_node structure * @param add_tail Specify if the cmd needs to be queued in the header or tail * * @return N/A */ t_void wlan_insert_cmd_to_pending_q(IN mlan_adapter * pmadapter, IN cmd_ctrl_node * pcmd_node, IN t_u32 add_tail) { HostCmd_DS_COMMAND *pcmd = MNULL; t_u16 command; ENTER(); if (pcmd_node == MNULL) { PRINTM(MERROR, "QUEUE_CMD: pcmd_node is MNULL\n"); goto done; } pcmd = (HostCmd_DS_COMMAND *) (pcmd_node->cmdbuf->pbuf + pcmd_node->cmdbuf->data_offset); if (pcmd == MNULL) { PRINTM(MERROR, "QUEUE_CMD: pcmd is MNULL\n"); goto done; } command = wlan_le16_to_cpu(pcmd->command); /* Exit_PS command needs to be queued in the header always. */ if (command == HostCmd_CMD_802_11_PS_MODE_ENH) { HostCmd_DS_802_11_PS_MODE_ENH *pm = &pcmd->params.psmode_enh; if (wlan_le16_to_cpu(pm->action) == DIS_PS) { if (pmadapter->ps_state != PS_STATE_AWAKE) add_tail = MFALSE; } } if (add_tail) { util_enqueue_list_tail(&pmadapter->cmd_pending_q, (pmlan_linked_list) pcmd_node, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); } else { util_enqueue_list_head(&pmadapter->cmd_pending_q, (pmlan_linked_list) pcmd_node, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); } PRINTM(MCMND, "QUEUE_CMD: cmd=0x%x is queued\n", command); done: LEAVE(); return; }
/** * @brief This function handles the command response of 11ncfg * * @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 */ mlan_status wlan_ret_11n_cfg(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND * resp, IN mlan_ioctl_req * pioctl_buf) { mlan_ds_11n_cfg *cfg = MNULL; HostCmd_DS_11N_CFG *htcfg = &resp->params.htcfg; ENTER(); if (pioctl_buf) { cfg = (mlan_ds_11n_cfg *) pioctl_buf->pbuf; cfg->param.tx_cfg.httxcap = wlan_le16_to_cpu(htcfg->ht_tx_cap); cfg->param.tx_cfg.httxinfo = wlan_le16_to_cpu(htcfg->ht_tx_info); } LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief This function handles the command response of * delete a block ack request * * @param priv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_ret_11n_delba(mlan_private * priv, HostCmd_DS_COMMAND * resp) { int tid; TxBAStreamTbl *ptx_ba_tbl; HostCmd_DS_11N_DELBA *pdel_ba = (HostCmd_DS_11N_DELBA *) & resp->params.del_ba; ENTER(); pdel_ba->del_ba_param_set = wlan_le16_to_cpu(pdel_ba->del_ba_param_set); pdel_ba->reason_code = wlan_le16_to_cpu(pdel_ba->reason_code); tid = pdel_ba->del_ba_param_set >> DELBA_TID_POS; if (pdel_ba->del_result == BA_RESULT_SUCCESS) { mlan_11n_delete_bastream_tbl(priv, tid, pdel_ba->peer_mac_addr, TYPE_DELBA_SENT, INITIATOR_BIT(pdel_ba->del_ba_param_set)); if ((ptx_ba_tbl = wlan_11n_get_txbastream_status(priv, BA_STREAM_SETUP_INPROGRESS))) { wlan_send_addba(priv, ptx_ba_tbl->tid, ptx_ba_tbl->ra); } } else { /* * In case of failure, recreate the deleted stream in * case we initiated the ADDBA */ if (INITIATOR_BIT(pdel_ba->del_ba_param_set)) { wlan_11n_create_txbastream_tbl(priv, pdel_ba->peer_mac_addr, tid, BA_STREAM_SETUP_INPROGRESS); if ((ptx_ba_tbl = wlan_11n_get_txbastream_status(priv, BA_STREAM_SETUP_INPROGRESS))) { mlan_11n_delete_bastream_tbl(priv, ptx_ba_tbl->tid, ptx_ba_tbl->ra, TYPE_DELBA_SENT, MTRUE); } } } LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief This function reads data from the card. * * @param pmadapter A pointer to mlan_adapter structure * @param type A pointer to keep type as data or command * @param nb A pointer to keep the data/cmd length returned in buffer * @param pmbuf A pointer to the SDIO data/cmd buffer * @param npayload the length of data/cmd buffer * @param ioport the SDIO ioport * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_sdio_card_to_host(mlan_adapter * pmadapter, t_u32 * type, t_u32 * nb, pmlan_buffer pmbuf, t_u32 npayload, t_u32 ioport) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb = &pmadapter->callbacks; ENTER(); if (!pmbuf) { PRINTM(MWARN, "pmbuf is NULL!\n"); ret = MLAN_STATUS_FAILURE; goto exit; } ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle, pmbuf, ioport, 0); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "card_to_host, read iomem failed: %d\n", ret); pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL; ret = MLAN_STATUS_FAILURE; goto exit; } *nb = wlan_le16_to_cpu(*(t_u16 *) (pmbuf->pbuf + pmbuf->data_offset)); if (*nb > npayload) { PRINTM(MERROR, "invalid packet, *nb=%d, npayload=%d\n", *nb, npayload); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; goto exit; } DBG_HEXDUMP(MIF_D, "SDIO Blk Rd", pmbuf->pbuf + pmbuf->data_offset, MIN(*nb, MAX_DATA_DUMP_LEN)); *type = wlan_le16_to_cpu(*(t_u16 *) (pmbuf->pbuf + pmbuf->data_offset + 2)); exit: LEAVE(); return ret; }
/** * @brief This function handle response of CMD_802_11D_DOMAIN_INFO * * @param pmpriv A pointer to mlan_private structure * @param resp Pointer to command response buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ret_802_11d_domain_info(mlan_private * pmpriv, HostCmd_DS_COMMAND * resp) { mlan_status ret = MLAN_STATUS_SUCCESS; HostCmd_DS_802_11D_DOMAIN_INFO_RSP *domain_info = &resp->params.domain_info_resp; MrvlIEtypes_DomainParamSet_t *domain = &domain_info->domain; t_u16 action = wlan_le16_to_cpu(domain_info->action); t_u8 no_of_sub_band = 0; ENTER(); /* Dump domain info response data */ HEXDUMP("11D: DOMAIN Info Rsp Data", (t_u8 *) resp, resp->size); no_of_sub_band = (t_u8) ((wlan_le16_to_cpu(domain->header.len) - 3) / sizeof(IEEEtypes_SubbandSet_t)); /* Country code is 3 bytes */ PRINTM(MINFO, "11D Domain Info Resp: number of sub-band=%d\n", no_of_sub_band); if (no_of_sub_band > MRVDRV_MAX_SUBBAND_802_11D) { PRINTM(MWARN, "11D: Invalid number of subbands %d returned!!\n", no_of_sub_band); LEAVE(); return MLAN_STATUS_FAILURE; } switch (action) { case HostCmd_ACT_GEN_SET: /* Proc Set Action */ break; case HostCmd_ACT_GEN_GET: break; default: PRINTM(MERROR, "11D: Invalid Action:%d\n", domain_info->action); ret = MLAN_STATUS_FAILURE; break; } LEAVE(); return ret; }
/** * @brief This function handles the command response of * add a block ack request * * @param priv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_ret_11n_addba_req(mlan_private * priv, HostCmd_DS_COMMAND * resp) { int tid; HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp = (HostCmd_DS_11N_ADDBA_RSP *) & resp->params.add_ba_rsp; TxBAStreamTbl *ptx_ba_tbl; ENTER(); padd_ba_rsp->block_ack_param_set = wlan_le16_to_cpu(padd_ba_rsp->block_ack_param_set); padd_ba_rsp->block_ack_tmo = wlan_le16_to_cpu(padd_ba_rsp->block_ack_tmo); padd_ba_rsp->ssn = (wlan_le16_to_cpu(padd_ba_rsp->ssn)) & SSN_MASK; padd_ba_rsp->status_code = wlan_le16_to_cpu(padd_ba_rsp->status_code); tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >> BLOCKACKPARAM_TID_POS; if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) { if ((ptx_ba_tbl = wlan_11n_get_txbastream_tbl(priv, tid, padd_ba_rsp-> peer_mac_addr))) { PRINTM(MINFO, "BA stream complete\n"); ptx_ba_tbl->ba_status = BA_STREAM_SETUP_COMPLETE; } else { PRINTM(MERROR, "BA stream not created\n"); } } else { mlan_11n_delete_bastream_tbl(priv, tid, padd_ba_rsp->peer_mac_addr, TYPE_DELBA_SENT, MTRUE); if (padd_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) { #ifdef UAP_SUPPORT if (priv->bss_type == MLAN_BSS_TYPE_UAP) disable_station_ampdu(priv, tid, padd_ba_rsp->peer_mac_addr); #endif /* UAP_SUPPORT */ priv->aggr_prio_tbl[tid].ampdu_ap = BA_STREAM_NOT_ALLOWED; } } LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief This function handles the command response of * delete a block ack request * * @param priv A pointer to mlan_private structure * @param del_ba A pointer to command response buffer * * @return N/A */ void wlan_11n_delete_bastream(mlan_private * priv, t_u8 * del_ba) { HostCmd_DS_11N_DELBA *pdel_ba = (HostCmd_DS_11N_DELBA *) del_ba; int tid; ENTER(); DBG_HEXDUMP(MCMD_D, "Delba:", (t_u8 *) pdel_ba, 20); pdel_ba->del_ba_param_set = wlan_le16_to_cpu(pdel_ba->del_ba_param_set); pdel_ba->reason_code = wlan_le16_to_cpu(pdel_ba->reason_code); tid = pdel_ba->del_ba_param_set >> DELBA_TID_POS; mlan_11n_delete_bastream_tbl(priv, tid, pdel_ba->peer_mac_addr, TYPE_DELBA_RECEIVE, INITIATOR_BIT(pdel_ba->del_ba_param_set)); LEAVE(); }
/** * @brief This function handles the command response of amsdu aggr ctrl * * @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 */ mlan_status wlan_ret_amsdu_aggr_ctrl(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND * resp, IN mlan_ioctl_req * pioctl_buf) { mlan_ds_11n_cfg *cfg = MNULL; HostCmd_DS_AMSDU_AGGR_CTRL *amsdu_ctrl = &resp->params.amsdu_aggr_ctrl; ENTER(); if (pioctl_buf) { cfg = (mlan_ds_11n_cfg *) pioctl_buf->pbuf; cfg->param.amsdu_aggr_ctrl.enable = wlan_le16_to_cpu(amsdu_ctrl->enable); cfg->param.amsdu_aggr_ctrl.curr_buf_size = wlan_le16_to_cpu(amsdu_ctrl->curr_buf_size); } LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief This function handles the command response of fw_wakeup_method * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ static int wlan_ret_fw_wakeup_method(WlanCard *cardInfo, HostCmd_DS_COMMAND * resp) { WlanCard *card = cardInfo; HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &resp->params.fwwakeupmethod; u16 action; action = wlan_le16_to_cpu(fwwm->Action); switch (action) { case HostCmd_ACT_GET: case HostCmd_ACT_SET: card->fwWakeupMethod = wlan_le16_to_cpu(fwwm->Method); break; default: break; } return WLAN_STATUS_SUCCESS; }
/** * @brief Debug print display of the input measurement report * * @param pmeas_rpt Pointer to measurement report to display * * @return N/A */ static void wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT * pmeas_rpt) { ENTER(); PRINTM(MINFO, "Meas: Rpt: ------------------------------\n"); PRINTM(MINFO, "Meas: Rpt: mac_addr: %02x:%02x:%02x:%02x:%02x:%02x\n", pmeas_rpt->mac_addr[0], pmeas_rpt->mac_addr[1], pmeas_rpt->mac_addr[2], pmeas_rpt->mac_addr[3], pmeas_rpt->mac_addr[4], pmeas_rpt->mac_addr[5]); PRINTM(MINFO, "Meas: Rpt: dlgTkn: %d\n", pmeas_rpt->dialog_token); PRINTM(MINFO, "Meas: Rpt: rptMode: (%x): Rfs[%c] ICp[%c] Lt[%c]\n", *(t_u8 *) & pmeas_rpt->rpt_mode, pmeas_rpt->rpt_mode.refused ? 'X' : ' ', pmeas_rpt->rpt_mode.incapable ? 'X' : ' ', pmeas_rpt->rpt_mode.late ? 'X' : ' '); #ifdef DEBUG_LEVEL2 PRINTM(MINFO, "Meas: Rpt: measTyp: %s\n", wlan_meas_get_meas_type_str(pmeas_rpt->meas_type)); #endif switch (pmeas_rpt->meas_type) { case WLAN_MEAS_BASIC: PRINTM(MINFO, "Meas: Rpt: chan: %u\n", pmeas_rpt->rpt.basic.channel); PRINTM(MINFO, "Meas: Rpt: strt: %llu\n", wlan_le64_to_cpu(pmeas_rpt->rpt.basic.start_time)); PRINTM(MINFO, "Meas: Rpt: dur: %u\n", wlan_le16_to_cpu(pmeas_rpt->rpt.basic.duration)); PRINTM(MINFO, "Meas: Rpt: bas: (%x): unmsd[%c], radar[%c]\n", *(t_u8 *) & (pmeas_rpt->rpt.basic.map), pmeas_rpt->rpt.basic.map.unmeasured ? 'X' : ' ', pmeas_rpt->rpt.basic.map.radar ? 'X' : ' '); PRINTM(MINFO, "Meas: Rpt: bas: unidSig[%c] ofdm[%c] bss[%c]\n", pmeas_rpt->rpt.basic.map.unidentified_sig ? 'X' : ' ', pmeas_rpt->rpt.basic.map.ofdm_preamble ? 'X' : ' ', pmeas_rpt->rpt.basic.map.bss ? 'X' : ' '); break; default: PRINTM(MINFO, "Meas: Rpt: <unhandled>\n"); break; } PRINTM(MINFO, "Meas: Rpt: ------------------------------\n"); LEAVE(); }
/** * @brief Debug print display of the input measurement request * * @param pmeas_req Pointer to the measurement request to display * * @return N/A */ static void wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST * pmeas_req) { ENTER(); PRINTM(MINFO, "Meas: Req: ------------------------------\n"); PRINTM(MINFO, "Meas: Req: mac_addr: %02x:%02x:%02x:%02x:%02x:%02x\n", pmeas_req->mac_addr[0], pmeas_req->mac_addr[1], pmeas_req->mac_addr[2], pmeas_req->mac_addr[3], pmeas_req->mac_addr[4], pmeas_req->mac_addr[5]); PRINTM(MINFO, "Meas: Req: dlgTkn: %d\n", pmeas_req->dialog_token); PRINTM(MINFO, "Meas: Req: mode: dm[%c] rpt[%c] req[%c]\n", pmeas_req->req_mode.duration_mandatory ? 'X' : ' ', pmeas_req->req_mode.report ? 'X' : ' ', pmeas_req->req_mode.request ? 'X' : ' '); PRINTM(MINFO, "Meas: Req: : en[%c] par[%c]\n", pmeas_req->req_mode.enable ? 'X' : ' ', pmeas_req->req_mode.parallel ? 'X' : ' '); #ifdef DEBUG_LEVEL2 PRINTM(MINFO, "Meas: Req: measTyp: %s\n", wlan_meas_get_meas_type_str(pmeas_req->meas_type)); #endif switch (pmeas_req->meas_type) { case WLAN_MEAS_BASIC: /* Lazy cheat, fields of bas, cca, rpi union match on the request */ PRINTM(MINFO, "Meas: Req: chan: %u\n", pmeas_req->req.basic.channel); PRINTM(MINFO, "Meas: Req: strt: %llu\n", wlan_le64_to_cpu(pmeas_req->req.basic.start_time)); PRINTM(MINFO, "Meas: Req: dur: %u\n", wlan_le16_to_cpu(pmeas_req->req.basic.duration)); break; default: PRINTM(MINFO, "Meas: Req: <unhandled>\n"); break; } PRINTM(MINFO, "Meas: Req: ------------------------------\n"); LEAVE(); }
/** * @brief This function handles the command response of rf_tx_power * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ static int wlan_ret_802_11_rf_tx_power(WlanCard *cardinfo, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_RF_TX_POWER *rtp = &resp->params.txp; WlanCard *card = cardinfo; u16 Action = (rtp->Action); card->TxPowerLevel = wlan_le16_to_cpu(rtp->CurrentLevel); if (Action == HostCmd_ACT_GET) { card->MaxTxPowerLevel = rtp->MaxPower; card->MinTxPowerLevel = rtp->MinPower; } WlanDebug(WlanMsg,"Current TxPower Level = %d,Max Power=%d, Min Power=%d\n", card->TxPowerLevel, card->MaxTxPowerLevel, card->MinTxPowerLevel); return WLAN_STATUS_SUCCESS; }
/** * @brief This function handles the command response of host_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_host_cmd(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND * resp, IN mlan_ioctl_req * pioctl_buf) { mlan_ds_misc_cfg *misc; t_u16 size = wlan_le16_to_cpu(resp->size); ENTER(); PRINTM(MINFO, "host command response size = %d\n", size); size = MIN(size, MRVDRV_SIZE_OF_CMD_BUFFER); if (pioctl_buf) { misc = (mlan_ds_misc_cfg *) pioctl_buf->pbuf; misc->param.hostcmd.len = size; memcpy(misc->param.hostcmd.cmd, (void *) resp, size); } LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief Check if intended address field is configured. * If yes, update the corresponding device ID. * @param wfd_buf WFD buffer pointer * @param wfd_buf_len WFD buffer length * * @return WPS_STATUS_SUCCESS--success, WPS_STATUS_FAIL--fail */ static int wfd_check_set_intended_addr(u8 *wfd_buf, u16 wfd_buf_len) { tlvbuf_wfd_intended_addr *wfd_tlv; u8 *ptr = wfd_buf; s16 left_len = wfd_buf_len; u16 len = 0; ENTER(); ptr += sizeof(wifidir_oui_type); while (left_len > WFD_IE_HEADER_LEN) { if (*ptr == TLV_TYPE_WFD_INTENDED_ADDRESS) { wfd_tlv = (tlvbuf_wfd_intended_addr *) ptr; /* Address is found, set it now */ wps_printf(DEBUG_WFD_DISCOVERY, "Intended address. " MACSTR, MAC2STR(wfd_tlv->group_address)); memcpy(gpwps_info->wfd_intended_addr, wfd_tlv->group_address, ETH_ALEN); LEAVE(); return WPS_STATUS_SUCCESS; } memcpy(&len, ptr + 1, sizeof(u16)); len = wlan_le16_to_cpu(len); ptr += len + WFD_IE_HEADER_LEN; left_len -= len + WFD_IE_HEADER_LEN; } LEAVE(); return WPS_STATUS_FAIL; }
/** * @brief Check if P2P capability attr is present in the P2P IE. * If yes, return the value of it. * @param wfd_buf WFD buffer pointer * @param wfd_buf_len WFD buffer length * @param dev_cap pointer to device capability * @param grp_cap pointer to group capability * * @return WPS_STATUS_SUCCESS--success, WPS_STATUS_FAIL--fail */ static int wfd_get_p2p_cap_attribute(u8 *wfd_buf, u16 wfd_buf_len, u8 *dev_cap, u8 *grp_cap) { tlvbuf_wfd_capability *wfd_tlv; u8 *ptr = wfd_buf; s16 left_len = wfd_buf_len; u16 len = 0; ENTER(); wps_hexdump(DEBUG_WLAN, "WFD IE:", (u8 *) wfd_buf, wfd_buf_len); ptr += sizeof(wifidir_oui_type); while (left_len > WFD_IE_HEADER_LEN) { if (*ptr == TLV_TYPE_WFD_CAPABILITY) { wfd_tlv = (tlvbuf_wfd_capability *) ptr; *dev_cap = wfd_tlv->dev_capability; *grp_cap = wfd_tlv->group_capability; LEAVE(); return WPS_STATUS_SUCCESS; } memcpy(&len, ptr + 1, sizeof(u16)); len = wlan_le16_to_cpu(len); ptr += len + WFD_IE_HEADER_LEN; left_len -= len + WFD_IE_HEADER_LEN; } LEAVE(); return WPS_STATUS_FAIL; }
/** * @brief This function will process tx pause event * * @param priv A pointer to mlan_private * @param pevent A pointer to event buf * * @return N/A */ static void wlan_process_sta_tx_pause_event(pmlan_private priv, pmlan_buffer pevent) { t_u16 tlv_type, tlv_len; int tlv_buf_left = pevent->data_len - sizeof(t_u32); MrvlIEtypesHeader_t *tlv = (MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset + sizeof(t_u32)); MrvlIEtypes_tx_pause_t *tx_pause_tlv; sta_node *sta_ptr = MNULL; tdlsStatus_e status; t_u8 *bssid = MNULL; ENTER(); if (priv->media_connected) bssid = priv->curr_bss_params.bss_descriptor.mac_address; while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) { tlv_type = wlan_le16_to_cpu(tlv->type); tlv_len = wlan_le16_to_cpu(tlv->len); if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) > (unsigned int)tlv_buf_left) { PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, tlv_buf_left); break; } if (tlv_type == TLV_TYPE_TX_PAUSE) { tx_pause_tlv = (MrvlIEtypes_tx_pause_t *)tlv; PRINTM(MCMND, "TxPause: " MACSTR " pause=%d, pkts=%d\n", MAC2STR(tx_pause_tlv->peermac), tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt); if (bssid && !memcmp(priv->adapter, bssid, tx_pause_tlv->peermac, MLAN_MAC_ADDR_LENGTH)) { if (tx_pause_tlv->tx_pause) priv->port_open = MFALSE; else priv->port_open = MTRUE; } else { status = wlan_get_tdls_link_status(priv, tx_pause_tlv-> peermac); if (MTRUE == wlan_is_tdls_link_setup(status)) { sta_ptr = wlan_get_station_entry(priv, tx_pause_tlv-> peermac); if (sta_ptr) { if (sta_ptr->tx_pause != tx_pause_tlv->tx_pause) { sta_ptr->tx_pause = tx_pause_tlv-> tx_pause; wlan_update_ralist_tx_pause (priv, tx_pause_tlv-> peermac, tx_pause_tlv-> tx_pause); } } } } } tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len); tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t)); } LEAVE(); return; }
/** * @brief This function processes received packet and forwards it * to kernel/upper layer * * @param adapter A pointer to mlan_adapter * @param pmbuf A pointer to mlan_buffer which includes the received packet * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_uap_process_rx_packet(IN t_void *adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter)adapter; mlan_status ret = MLAN_STATUS_SUCCESS; UapRxPD *prx_pd; wlan_mgmt_pkt *puap_pkt_hdr = MNULL; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; sta_node *sta_ptr = MNULL; t_u8 adj_rx_rate = 0; ENTER(); prx_pd = (UapRxPD *)(pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ uap_endian_convert_RxPD(prx_pd); priv->rxpd_rate = prx_pd->rx_rate; priv->rxpd_rate_info = prx_pd->rate_info; if (!priv->adapter->psdio_device->v15_fw_api) priv->rxpd_rate_info = wlan_convert_v14_rate_ht_info(priv->rxpd_rate_info); if (priv->bss_type == MLAN_BSS_TYPE_UAP) { adj_rx_rate = wlan_adjust_data_rate(priv, priv->rxpd_rate, priv->rxpd_rate_info); pmadapter->callbacks.moal_hist_data_add(pmadapter->pmoal_handle, pmbuf->bss_index, adj_rx_rate, prx_pd->snr, prx_pd->nf, prx_pd->antenna); } rx_pkt_type = prx_pd->rx_pkt_type; prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); PRINTM(MINFO, "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, pmbuf->data_len - prx_pd->rx_pkt_offset); if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) != (t_u16)pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) { /* Check if this is mgmt packet and needs to forwarded to app as an event */ puap_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); puap_pkt_hdr->frm_len = wlan_le16_to_cpu(puap_pkt_hdr->frm_len); if ((puap_pkt_hdr->wlan_header. frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0) wlan_process_802dot11_mgmt_pkt(pmadapter-> priv[pmbuf->bss_index], (t_u8 *)&puap_pkt_hdr-> wlan_header, puap_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(puap_pkt_hdr-> frm_len), (RxPD *)prx_pd); wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->priority = prx_pd->priority; memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) { sta_ptr = wlan_get_station_entry(priv, ta); if (sta_ptr) sta_ptr->rx_seq[prx_pd->priority] = prx_pd->seq_num; } /* check if UAP enable 11n */ if (!priv->is_11n_enabled || (!wlan_11n_get_rxreorder_tbl ((mlan_private *)priv, prx_pd->priority, ta) && (prx_pd->rx_pkt_type != PKT_TYPE_AMSDU) )) { if (priv->pkt_fwd) wlan_process_uap_rx_packet(priv, pmbuf); else wlan_upload_uap_rx_packet(pmadapter, pmbuf); goto done; } /* Reorder and send to OS */ ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type, (void *)pmbuf); if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { wlan_free_mlan_buffer(pmadapter, pmbuf); } done: LEAVE(); return ret; }
/** * @brief This function handles events generated by firmware * * @param priv A pointer to mlan_private structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status mlan_process_sta_event(IN t_void * priv) { pmlan_private pmpriv = (pmlan_private) priv; pmlan_adapter pmadapter = pmpriv->adapter; mlan_status ret = MLAN_STATUS_SUCCESS; t_u32 eventcause = pmadapter->event_cause; t_u8 event_buf[100]; t_u8 *evt_buf = MNULL; pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event; mlan_event *pevent = (mlan_event *) event_buf; ENTER(); if (pmbuf) memcpy(pmadapter, pmbuf->pbuf + pmbuf->data_offset, (t_u8 *) & eventcause, sizeof(eventcause)); switch (eventcause) { case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: PRINTM(MERROR, "Invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignoring it\n"); break; case EVENT_LINK_SENSED: PRINTM(MEVENT, "EVENT: LINK_SENSED\n"); pmpriv->adhoc_is_link_sensed = MTRUE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED, MNULL); break; case EVENT_DEAUTHENTICATED: PRINTM(MEVENT, "EVENT: Deauthenticated\n"); pmadapter->dbg.num_event_deauth++; wlan_handle_disconnect_event(pmpriv); break; case EVENT_DISASSOCIATED: PRINTM(MEVENT, "EVENT: Disassociated\n"); pmadapter->dbg.num_event_disassoc++; wlan_handle_disconnect_event(pmpriv); break; case EVENT_LINK_LOST: PRINTM(MEVENT, "EVENT: Link lost\n"); pmadapter->dbg.num_event_link_lost++; wlan_handle_disconnect_event(pmpriv); break; case EVENT_PS_SLEEP: PRINTM(MINFO, "EVENT: SLEEP\n"); PRINTM(MEVENT, "_"); /* Handle unexpected PS SLEEP event */ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) break; pmadapter->ps_state = PS_STATE_PRE_SLEEP; wlan_check_ps_cond(pmadapter); break; case EVENT_PS_AWAKE: PRINTM(MINFO, "EVENT: AWAKE \n"); PRINTM(MEVENT, "|"); if (!pmadapter->pps_uapsd_mode && pmpriv->media_connected && pmadapter->sleep_period.period) { pmadapter->pps_uapsd_mode = MTRUE; PRINTM(MEVENT, "PPS/UAPSD mode activated\n"); } /* Handle unexpected PS AWAKE event */ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) break; pmadapter->tx_lock_flag = MFALSE; if (pmadapter->pps_uapsd_mode && pmadapter->gen_null_pkt) { if (MTRUE == wlan_check_last_packet_indication(pmpriv)) { if (!pmadapter->data_sent) { if (wlan_send_null_packet(pmpriv, MRVDRV_TxPD_POWER_MGMT_NULL_PACKET | MRVDRV_TxPD_POWER_MGMT_LAST_PACKET) == MLAN_STATUS_SUCCESS) { return MLAN_STATUS_SUCCESS; } } } } pmadapter->ps_state = PS_STATE_AWAKE; pmadapter->pm_wakeup_card_req = MFALSE; pmadapter->pm_wakeup_fw_try = MFALSE; break; case EVENT_HS_ACT_REQ: PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n"); ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, 0, 0, MNULL, MNULL); break; case EVENT_MIC_ERR_UNICAST: PRINTM(MEVENT, "EVENT: UNICAST MIC ERROR\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_UNI, MNULL); break; case EVENT_MIC_ERR_MULTICAST: PRINTM(MEVENT, "EVENT: MULTICAST MIC ERROR\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_MUL, MNULL); break; case EVENT_MIB_CHANGED: case EVENT_INIT_DONE: break; case EVENT_ADHOC_BCN_LOST: PRINTM(MEVENT, "EVENT: ADHOC_BCN_LOST\n"); pmpriv->adhoc_is_link_sensed = MFALSE; wlan_clean_txrx(pmpriv); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_LOST, MNULL); break; case EVENT_BG_SCAN_REPORT: PRINTM(MEVENT, "EVENT: BGS_REPORT\n"); /* Clear the previous scan result */ memset(pmadapter, pmadapter->pscan_table, 0x00, sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST); pmadapter->num_in_scan_table = 0; pmadapter->pbcn_buf_end = pmadapter->bcn_buf; ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_BG_SCAN_QUERY, HostCmd_ACT_GEN_GET, 0, MNULL, MNULL); break; case EVENT_PORT_RELEASE: PRINTM(MEVENT, "EVENT: PORT RELEASE\n"); /* Open the port for e-supp mode */ if (pmpriv->port_ctrl_mode == MTRUE) { PRINTM(MINFO, "PORT_REL: port_status = OPEN\n"); pmpriv->port_open = MTRUE; } pmpriv->scan_block = MFALSE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PORT_RELEASE, MNULL); break; case EVENT_STOP_TX: PRINTM(MEVENT, "EVENT: Stop Tx (%#x)\n", eventcause); wlan_11h_tx_disable(pmpriv); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_STOP_TX, MNULL); break; case EVENT_START_TX: PRINTM(MEVENT, "EVENT: Start Tx (%#x)\n", eventcause); wlan_11h_tx_enable(pmpriv); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_START_TX, MNULL); break; case EVENT_CHANNEL_SWITCH: PRINTM(MEVENT, "EVENT: Channel Switch (%#x)\n", eventcause); /* To be handled for 'chanswann' private command */ break; case EVENT_CHANNEL_SWITCH_ANN: PRINTM(MEVENT, "EVENT: Channel Switch Announcement\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN, MNULL); wlan_11h_handle_event_chanswann(pmpriv); break; case EVENT_MEAS_REPORT_RDY: PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n", eventcause); wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT, HostCmd_ACT_GEN_SET, 0, 0, MNULL); break; case EVENT_WMM_STATUS_CHANGE: if (pmbuf && pmbuf->data_len > sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) { PRINTM(MEVENT, "EVENT: WMM status changed: %d\n", pmbuf->data_len); evt_buf = (pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)); wlan_ret_wmm_get_status(pmpriv, evt_buf, pmbuf->data_len - sizeof(eventcause)); } else { PRINTM(MEVENT, "EVENT: WMM status changed\n"); ret = wlan_cmd_wmm_status_change(pmpriv); } break; case EVENT_RSSI_LOW: PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_RSSI_LOW, MNULL); break; case EVENT_SNR_LOW: PRINTM(MEVENT, "EVENT: Beacon SNR_LOW\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_LOW, MNULL); break; case EVENT_MAX_FAIL: PRINTM(MEVENT, "EVENT: MAX_FAIL\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MAX_FAIL, MNULL); break; case EVENT_RSSI_HIGH: PRINTM(MEVENT, "EVENT: Beacon RSSI_HIGH\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_RSSI_HIGH, MNULL); break; case EVENT_SNR_HIGH: PRINTM(MEVENT, "EVENT: Beacon SNR_HIGH\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_HIGH, MNULL); break; case EVENT_DATA_RSSI_LOW: PRINTM(MEVENT, "EVENT: Data RSSI_LOW\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_LOW, MNULL); break; case EVENT_DATA_SNR_LOW: PRINTM(MEVENT, "EVENT: Data SNR_LOW\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_LOW, MNULL); break; case EVENT_DATA_RSSI_HIGH: PRINTM(MEVENT, "EVENT: Data RSSI_HIGH\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, MNULL); break; case EVENT_DATA_SNR_HIGH: PRINTM(MEVENT, "EVENT: Data SNR_HIGH\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_HIGH, MNULL); break; case EVENT_LINK_QUALITY: PRINTM(MEVENT, "EVENT: Link Quality\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_LINK_QUALITY, MNULL); break; case EVENT_PRE_BEACON_LOST: PRINTM(MEVENT, "EVENT: Pre-Beacon Lost\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PRE_BCN_LOST, MNULL); break; case EVENT_IBSS_COALESCED: PRINTM(MEVENT, "EVENT: IBSS_COALESCED\n"); ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, HostCmd_ACT_GEN_GET, 0, MNULL, MNULL); break; case EVENT_ADDBA: PRINTM(MEVENT, "EVENT: ADDBA Request\n"); wlan_prepare_cmd(pmpriv, HostCmd_CMD_11N_ADDBA_RSP, HostCmd_ACT_GEN_SET, 0, MNULL, pmadapter->event_body); break; case EVENT_DELBA: PRINTM(MEVENT, "EVENT: DELBA Request\n"); wlan_11n_delete_bastream(pmpriv, pmadapter->event_body); break; case EVENT_BA_STREAM_TIMEOUT: PRINTM(MEVENT, "EVENT: BA Stream timeout\n"); wlan_11n_ba_stream_timeout(pmpriv, (HostCmd_DS_11N_BATIMEOUT *) pmadapter-> event_body); break; case EVENT_AMSDU_AGGR_CTRL: PRINTM(MEVENT, "EVENT: AMSDU_AGGR_CTRL %d\n", *(t_u16 *) pmadapter->event_body); pmadapter->tx_buf_size = MIN(pmadapter->curr_tx_buf_size, wlan_le16_to_cpu(*(t_u16 *) pmadapter->event_body)); PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size); break; case EVENT_WEP_ICV_ERR: PRINTM(MEVENT, "EVENT: WEP ICV error\n"); pevent->bss_num = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_WEP_ICV_ERR; pevent->event_len = sizeof(Event_WEP_ICV_ERR); memcpy(pmadapter, (t_u8 *) pevent->event_buf, pmadapter->event_body, pevent->event_len); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_WEP_ICV_ERR, pevent); break; case EVENT_BW_CHANGE: PRINTM(MEVENT, "EVENT: BW Change\n"); pevent->bss_num = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_BW_CHANGED; pevent->event_len = sizeof(t_u8); /* Copy event body from the event buffer */ memcpy(pmadapter, (t_u8 *) pevent->event_buf, pmadapter->event_body, pevent->event_len); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BW_CHANGED, pevent); break; default: PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL); break; } LEAVE(); return ret; }
/** * @brief This function will parse the TDLS event for further wlan action * * @param priv A pointer to mlan_private * @param pevent A pointer to event buf * * @return N/A */ static void wlan_parse_tdls_event(pmlan_private priv, pmlan_buffer pevent) { Event_tdls_generic *tdls_event = (Event_tdls_generic *) (pevent->pbuf + pevent->data_offset + sizeof(mlan_event_id)); sta_node *sta_ptr = MNULL; pmlan_adapter pmadapter = priv->adapter; t_u8 i = 0; IEEEtypes_HTCap_t *pht_cap = MNULL; t_u16 ie_len = 0; mlan_ds_misc_tdls_oper tdls_oper; t_u8 event_buf[100]; mlan_event *ptdls_event = (mlan_event *)event_buf; tdls_tear_down_event *tdls_evt = (tdls_tear_down_event *)ptdls_event->event_buf; ENTER(); /* reason code is not mandatory, hence less by sizeof(t_u16) */ if (pevent->data_len < (sizeof(Event_tdls_generic) - sizeof(t_u16) - sizeof(mlan_event_id))) { PRINTM(MERROR, "Invalid length %d for TDLS event\n", pevent->data_len); LEAVE(); return; } sta_ptr = wlan_get_station_entry(priv, tdls_event->peer_mac_addr); PRINTM(MEVENT, "TDLS_EVENT: %d " MACSTR "\n", wlan_le16_to_cpu(tdls_event->event_type), MAC2STR(tdls_event->peer_mac_addr)); switch (wlan_le16_to_cpu(tdls_event->event_type)) { case TDLS_EVENT_TYPE_SETUP_REQ: if (sta_ptr == MNULL) { sta_ptr = wlan_add_station_entry(priv, tdls_event-> peer_mac_addr); if (sta_ptr) { sta_ptr->status = TDLS_SETUP_INPROGRESS; wlan_hold_tdls_packets(priv, tdls_event-> peer_mac_addr); } } break; case TDLS_EVENT_TYPE_LINK_ESTABLISHED: if (sta_ptr) { sta_ptr->status = TDLS_SETUP_COMPLETE; /* parse the TLV for station's capability */ ie_len = wlan_le16_to_cpu(tdls_event->u.ie_data. ie_length); if (ie_len) { pht_cap = (IEEEtypes_HTCap_t *) wlan_get_specific_ie(priv, tdls_event->u. ie_data.ie_ptr, ie_len, HT_CAPABILITY); if (pht_cap) { sta_ptr->is_11n_enabled = MTRUE; if (GETHT_MAXAMSDU (pht_cap->ht_cap.ht_cap_info)) sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K; else sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K; } } for (i = 0; i < MAX_NUM_TID; i++) { if (sta_ptr->is_11n_enabled) sta_ptr->ampdu_sta[i] = priv->aggr_prio_tbl[i]. ampdu_user; else sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; } memset(priv->adapter, sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); wlan_restore_tdls_packets(priv, tdls_event->peer_mac_addr, TDLS_SETUP_COMPLETE); pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL; } break; case TDLS_EVENT_TYPE_SETUP_FAILURE: wlan_restore_tdls_packets(priv, tdls_event->peer_mac_addr, TDLS_SETUP_FAILURE); if (sta_ptr) wlan_delete_station_entry(priv, tdls_event->peer_mac_addr); if (MTRUE == wlan_is_station_list_empty(priv)) pmadapter->tdls_status = TDLS_NOT_SETUP; else pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL; break; case TDLS_EVENT_TYPE_LINK_TORN_DOWN: if (sta_ptr) { if (sta_ptr->external_tdls) { PRINTM(MMSG, "Receive TDLS TEAR DOWN event, Disable TDLS LINK\n"); memset(pmadapter, &tdls_oper, 0, sizeof(tdls_oper)); tdls_oper.tdls_action = WLAN_TDLS_DISABLE_LINK; memcpy(priv->adapter, tdls_oper.peer_mac, tdls_event->peer_mac_addr, MLAN_MAC_ADDR_LENGTH); /* Send command to firmware to delete tdls link */ wlan_prepare_cmd(priv, HostCmd_CMD_TDLS_OPERATION, HostCmd_ACT_GEN_SET, 0, (t_void *)MNULL, &tdls_oper); ptdls_event->bss_index = priv->bss_index; ptdls_event->event_id = MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ; ptdls_event->event_len = sizeof(tdls_tear_down_event); memcpy(priv->adapter, (t_u8 *)tdls_evt->peer_mac_addr, tdls_event->peer_mac_addr, MLAN_MAC_ADDR_LENGTH); tdls_evt->reason_code = wlan_le16_to_cpu(tdls_event->u. reason_code); wlan_recv_event(priv, MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ, ptdls_event); /* Signal MOAL to trigger mlan_main_process */ wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL); LEAVE(); return; } wlan_restore_tdls_packets(priv, tdls_event->peer_mac_addr, TDLS_TEAR_DOWN); if (sta_ptr->is_11n_enabled) { wlan_cleanup_reorder_tbl(priv, tdls_event-> peer_mac_addr); pmadapter->callbacks.moal_spin_lock(pmadapter-> pmoal_handle, priv->wmm. ra_list_spinlock); wlan_11n_cleanup_txbastream_tbl(priv, tdls_event-> peer_mac_addr); pmadapter->callbacks. moal_spin_unlock(pmadapter-> pmoal_handle, priv->wmm. ra_list_spinlock); } wlan_delete_station_entry(priv, tdls_event->peer_mac_addr); if (MTRUE == wlan_is_station_list_empty(priv)) pmadapter->tdls_status = TDLS_NOT_SETUP; else pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL; } break; case TDLS_EVENT_TYPE_CHAN_SWITCH_RESULT: PRINTM(MEVENT, "TDLS_CHAN_SWITCH_RESULT: status=0x%x, reason=0x%x current_channel=%d\n", tdls_event->u.switch_result.status, tdls_event->u.switch_result.reason, (int)tdls_event->u.switch_result.current_channel); if (tdls_event->u.switch_result.status == MLAN_STATUS_SUCCESS) { if (tdls_event->u.switch_result.current_channel == TDLS_BASE_CHANNEL) { /* enable traffic to AP */ if (pmadapter->tdls_status != TDLS_IN_BASE_CHANNEL) { wlan_update_non_tdls_ralist(priv, tdls_event-> peer_mac_addr, MFALSE); pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL; } } else if (tdls_event->u.switch_result. current_channel == TDLS_OFF_CHANNEL) { /* pause traffic to AP */ if (pmadapter->tdls_status != TDLS_IN_OFF_CHANNEL) { wlan_update_non_tdls_ralist(priv, tdls_event-> peer_mac_addr, MTRUE); pmadapter->tdls_status = TDLS_IN_OFF_CHANNEL; } } } else { if (tdls_event->u.switch_result.current_channel == TDLS_BASE_CHANNEL) pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL; else if (tdls_event->u.switch_result.current_channel == TDLS_OFF_CHANNEL) pmadapter->tdls_status = TDLS_IN_OFF_CHANNEL; } break; case TDLS_EVENT_TYPE_START_CHAN_SWITCH: PRINTM(MEVENT, "TDLS start channel switch....\n"); pmadapter->tdls_status = TDLS_SWITCHING_CHANNEL; break; case TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED: PRINTM(MEVENT, "TDLS channel switch stopped, reason=%d\n", tdls_event->u.cs_stop_reason); break; case TDLS_EVENT_TYPE_DEBUG: case TDLS_EVENT_TYPE_PACKET: break; default: PRINTM(MERROR, "unknown event type %d\n", wlan_le16_to_cpu(tdls_event->event_type)); break; } LEAVE(); }
/** * @brief This function receives data from the card in aggregate mode. * * @param pmadapter A pointer to mlan_adapter structure * @param pmbuf A pointer to the SDIO data/cmd buffer * @param port Current port on which packet needs to be rxed * @param rx_len Length of received packet * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_sdio_card_to_host_mp_aggr(mlan_adapter * pmadapter, mlan_buffer * pmbuf, t_u8 port, t_u16 rx_len) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb = &pmadapter->callbacks; t_s32 f_do_rx_aggr = 0; t_s32 f_do_rx_cur = 0; t_s32 f_aggr_cur = 0; mlan_buffer mbuf_aggr; mlan_buffer *mbuf_deaggr; t_u32 pind = 0; t_u32 pkt_len, pkt_type = 0; t_u8 *curr_ptr; t_u32 cmd53_port = 0; ENTER(); if (port == CTRL_PORT) { /* Read the command response or event without aggr */ PRINTM(MINFO, "card_2_host_mp_aggr: No aggr for control port\n"); f_do_rx_cur = 1; goto rx_curr_single; } if (!pmadapter->mpa_rx.enabled) { PRINTM(MINFO, "card_2_host_mp_aggr: rx aggregation disabled !\n"); f_do_rx_cur = 1; goto rx_curr_single; } if (pmadapter->mp_rd_bitmap & (~((t_u32) CTRL_PORT_MASK))) { /* Some more data RX pending */ PRINTM(MINFO, "card_2_host_mp_aggr: Not last packet\n"); if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) { if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) { f_aggr_cur = 1; } else { /* No room in Aggr buf, do rx aggr now */ f_do_rx_aggr = 1; f_do_rx_cur = 1; } } else { /* Rx aggr not in progress */ f_aggr_cur = 1; } } else { /* No more data RX pending */ PRINTM(MINFO, "card_2_host_mp_aggr: Last packet\n"); if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) { f_do_rx_aggr = 1; if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) { f_aggr_cur = 1; } else { /* No room in Aggr buf, do rx aggr now */ f_do_rx_cur = 1; } } else { f_do_rx_cur = 1; } } if (f_aggr_cur) { PRINTM(MINFO, "Current packet aggregation.\n"); /* Curr pkt can be aggregated */ MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len); if (MP_RX_AGGR_PKT_LIMIT_REACHED(pmadapter) || MP_RX_AGGR_PORT_LIMIT_REACHED(pmadapter)) { PRINTM(MINFO, "card_2_host_mp_aggr: Aggregation Packet limit reached\n"); /* No more pkts allowed in Aggr buf, rx it */ f_do_rx_aggr = 1; } } if (f_do_rx_aggr) { /* do aggr RX now */ PRINTM(MINFO, "do_rx_aggr: num of packets: %d\n", pmadapter->mpa_rx.pkt_cnt); memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer)); mbuf_aggr.pbuf = (t_u8 *) pmadapter->mpa_rx.buf; mbuf_aggr.data_len = pmadapter->mpa_rx.buf_len; cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE | (pmadapter->mpa_rx.ports << 4)) + pmadapter->mpa_rx.start_port; if (MLAN_STATUS_SUCCESS != pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf_aggr, cmd53_port, 0)) { pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL; ret = MLAN_STATUS_FAILURE; goto done; } DBG_HEXDUMP(MIF_D, "SDIO MP-A Blk Rd", pmadapter->mpa_rx.buf, MIN(pmadapter->mpa_rx.buf_len, MAX_DATA_DUMP_LEN)); curr_ptr = pmadapter->mpa_rx.buf; for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) { /* get curr PKT len & type */ pkt_len = wlan_le16_to_cpu(*(t_u16 *) & curr_ptr[0]); pkt_type = wlan_le16_to_cpu(*(t_u16 *) & curr_ptr[2]); PRINTM(MINFO, "RX: [%d] pktlen: %d pkt_type: 0x%x\n", pind, pkt_len, pkt_type); /* copy pkt to deaggr buf */ mbuf_deaggr = pmadapter->mpa_rx.mbuf_arr[pind]; if ((pkt_type == MLAN_TYPE_DATA) && (pkt_len <= pmadapter->mpa_rx.len_arr[pind])) { memcpy(pmadapter, mbuf_deaggr->pbuf + mbuf_deaggr->data_offset, curr_ptr, pkt_len); pmadapter->upld_len = pkt_len; /* Process de-aggr packet */ wlan_decode_rx_packet(pmadapter, mbuf_deaggr, pkt_type); } else { PRINTM(MERROR, "Wrong aggr packet: type=%d, len=%d, max_len=%d\n", pkt_type, pkt_len, pmadapter->mpa_rx.len_arr[pind]); wlan_free_mlan_buffer(pmadapter, mbuf_deaggr); } curr_ptr += pmadapter->mpa_rx.len_arr[pind]; } MP_RX_AGGR_BUF_RESET(pmadapter); } rx_curr_single: if (f_do_rx_cur) { PRINTM(MINFO, "RX: f_do_rx_cur: port: %d rx_len: %d\n", port, rx_len); if (MLAN_STATUS_SUCCESS != wlan_sdio_card_to_host(pmadapter, &pkt_type, (t_u32 *) & pmadapter->upld_len, pmbuf, rx_len, pmadapter->ioport + port)) { ret = MLAN_STATUS_FAILURE; goto done; } if ((port == CTRL_PORT) && ((pkt_type != MLAN_TYPE_EVENT) && (pkt_type != MLAN_TYPE_CMD))) { PRINTM(MERROR, "Wrong pkt from CTRL PORT: type=%d, len=%dd\n", pkt_type, pmbuf->data_len); pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL; ret = MLAN_STATUS_FAILURE; goto done; } wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type); } done: if (ret == MLAN_STATUS_FAILURE) { if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) { /* MP-A transfer failed - cleanup */ for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) { wlan_free_mlan_buffer(pmadapter, pmadapter->mpa_rx. mbuf_arr[pind]); } MP_RX_AGGR_BUF_RESET(pmadapter); } if (f_do_rx_cur) { /* Single Transfer pending */ /* Free curr buff also */ wlan_free_mlan_buffer(pmadapter, pmbuf); } } LEAVE(); return ret; }
/** * @brief This function processes the received buffer * * @param adapter A pointer to mlan_adapter * @param pmbuf A pointer to the received buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_sta_process_rx_packet(IN t_void * adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter) adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPD *prx_pd; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL; ENTER(); prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ endian_convert_RxPD(prx_pd); rx_pkt_type = prx_pd->rx_pkt_type; prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16) pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) { /* Check if this is mgmt packet and needs to forwarded to app as an event */ pmgmt_pkt_hdr = (wlan_mgmt_pkt *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); pmgmt_pkt_hdr->frm_len = wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len); if ((pmgmt_pkt_hdr->wlan_header.frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0) wlan_process_802dot11_mgmt_pkt(pmadapter-> priv[pmbuf->bss_index], (t_u8 *) & pmgmt_pkt_hdr-> wlan_header, pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr-> frm_len)); wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if (!IS_11N_ENABLED(priv) || memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) { wlan_process_rx_packet(pmadapter, pmbuf); goto done; } if (queuing_ra_based(priv)) { memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); } else { if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) priv->rx_seq[prx_pd->priority] = prx_pd->seq_num; memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH); } /* Reorder and send to OS */ if ((ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8) prx_pd->rx_pkt_type, (void *)pmbuf)) || (rx_pkt_type == PKT_TYPE_BAR) ) { wlan_free_mlan_buffer(pmadapter, pmbuf); } done: LEAVE(); return (ret); }
/** * @brief This function processes the received buffer * * @param adapter A pointer to mlan_adapter * @param pmbuf A pointer to the received buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_sta_process_rx_packet(IN t_void *adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter)adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPD *prx_pd; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL; sta_node *sta_ptr = MNULL; ENTER(); prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ endian_convert_RxPD(prx_pd); rx_pkt_type = prx_pd->rx_pkt_type; prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16)pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) { /* Check if this is mgmt packet and needs to forwarded to app as an event */ pmgmt_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); pmgmt_pkt_hdr->frm_len = wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len); if ((pmgmt_pkt_hdr->wlan_header.frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0){ wlan_process_802dot11_mgmt_pkt(pmadapter-> priv[pmbuf->bss_index], (t_u8 *)&pmgmt_pkt_hdr-> wlan_header, pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr-> frm_len),prx_pd); wlan_sta_check_mgmt_frame(pmadapter->priv[pmbuf->bss_index], (t_u8 *) &pmgmt_pkt_hdr->wlan_header, pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr->frm_len), prx_pd); } wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if ((!IS_11N_ENABLED(priv) && !(prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) || memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) { wlan_process_rx_packet(pmadapter, pmbuf); goto done; } if (queuing_ra_based(priv) || (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) { memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); if ((prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK) && (prx_pd->priority < MAX_NUM_TID)) { PRINTM(MDATA, "tdls packet %p " MACSTR "\n", pmbuf, MAC2STR(ta)); sta_ptr = wlan_get_station_entry(priv, ta); if (sta_ptr) { sta_ptr->rx_seq[prx_pd->priority] = prx_pd->seq_num; sta_ptr->snr = prx_pd->snr; sta_ptr->nf = prx_pd->nf; pmadapter->callbacks. moal_updata_peer_signal(pmadapter-> pmoal_handle, pmbuf-> bss_index, ta, prx_pd->snr, prx_pd->nf); } } } else { if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) priv->rx_seq[prx_pd->priority] = prx_pd->seq_num; memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH); } if ((priv->port_ctrl_mode == MTRUE && priv->port_open == MFALSE) && (rx_pkt_type != PKT_TYPE_BAR)) { mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type, (t_void *)RX_PKT_DROPPED_IN_FW); wlan_process_rx_packet(pmadapter, pmbuf); goto done; } /* Reorder and send to OS */ ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type, (void *)pmbuf); if (ret || (rx_pkt_type == PKT_TYPE_BAR) ) { wlan_free_mlan_buffer(pmadapter, pmbuf); } done: LEAVE(); return ret; }
/** * @brief This function processes the received buffer * * @param adapter A pointer to mlan_adapter * @param pmbuf A pointer to the received buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_sta_process_rx_packet(IN t_void * adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter) adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPD *prx_pd; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; /* wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL; */ ENTER(); prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ endian_convert_RxPD(prx_pd); rx_pkt_type = prx_pd->rx_pkt_type; /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */ /* prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */ prx_pkt = (RxPacketHdr_t *) pmbuf->pdesc; /* wmprintf("%p + %d: O: %d PL: %d DL: %d\n\r", */ /* pmbuf->pbuf, pmbuf->data_offset, */ /* prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length, pmbuf->data_len); */ if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16) pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) { /* Check if this is mgmt packet and needs to forwarded to app as an event */ /* fixme */ wmprintf("Is a management packet expected here?\n\r"); os_enter_critical_section(); while(1){} #ifndef CONFIG_MLAN_WMSDK /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */ /* pmgmt_pkt_hdr = */ /* (wlan_mgmt_pkt *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */ pmgmt_pkt_hdr = (wlan_mgmt_pkt *)pmbuf->pdesc; pmgmt_pkt_hdr->frm_len = wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len); if ((pmgmt_pkt_hdr->wlan_header.frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0) wlan_process_802dot11_mgmt_pkt(pmadapter->priv[pmbuf->bss_index], (t_u8 *) & pmgmt_pkt_hdr-> wlan_header, pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr->frm_len)); wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; #endif /* CONFIG_MLAN_WMSDK */ } #ifdef DUMP_PACKET_MAC dump_mac_addr("Own: ", priv->curr_addr); dump_mac_addr("Dest: ", prx_pkt->eth803_hdr.dest_addr); #endif /* DUMP_PACKET_MAC */ /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if (!IS_11N_ENABLED(priv) || memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) { wlan_process_rx_packet(pmadapter, pmbuf); goto done; } if (queuing_ra_based(priv)) { memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); } else { if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) priv->rx_seq[prx_pd->priority] = prx_pd->seq_num; memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH); } /* Reorder and send to OS */ if ((ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8) prx_pd->rx_pkt_type, (void *) pmbuf)) || (rx_pkt_type == PKT_TYPE_BAR) ) { wlan_free_mlan_buffer(pmadapter, pmbuf); } done: LEAVE(); return (ret); }
/** * @brief This function handles events generated by firmware * * @param priv A pointer to mlan_private structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_sta_process_event(IN t_void *priv) { pmlan_private pmpriv = (pmlan_private)priv; pmlan_adapter pmadapter = pmpriv->adapter; mlan_status ret = MLAN_STATUS_SUCCESS; t_u32 eventcause = pmadapter->event_cause; t_u8 event_buf[100]; t_u8 *evt_buf = MNULL; pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event; t_u16 reason_code; pmlan_callbacks pcb = &pmadapter->callbacks; mlan_event *pevent = (mlan_event *)event_buf; ENTER(); /* Event length check */ if ((pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) { pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; LEAVE(); return MLAN_STATUS_FAILURE; } if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE && pmbuf->data_len > sizeof(eventcause)) DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len); switch (eventcause) { case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: PRINTM(MERROR, "Invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignoring it\n"); break; case EVENT_LINK_SENSED: PRINTM(MEVENT, "EVENT: LINK_SENSED\n"); pmpriv->adhoc_is_link_sensed = MTRUE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED, MNULL); break; case EVENT_DEAUTHENTICATED: if (pmpriv->wps.session_enable) { PRINTM(MMSG, "wlan: Recevie deauth event in wps session\n"); break; } reason_code = *(t_u16 *)(pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)); PRINTM(MMSG, "wlan: EVENT: Deauthenticated (reason 0x%x)\n", reason_code); pmadapter->dbg.num_event_deauth++; wlan_handle_disconnect_event(pmpriv); break; case EVENT_DISASSOCIATED: if (pmpriv->wps.session_enable) { PRINTM(MMSG, "wlan: Recevie disassociate event in wps session\n"); break; } reason_code = *(t_u16 *)(pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)); PRINTM(MMSG, "wlan: EVENT: Disassociated (reason 0x%x)\n", reason_code); pmadapter->dbg.num_event_disassoc++; wlan_handle_disconnect_event(pmpriv); break; case EVENT_LINK_LOST: reason_code = *(t_u16 *)(pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)); PRINTM(MMSG, "wlan: EVENT: Link lost (reason 0x%x)\n", reason_code); pmadapter->dbg.num_event_link_lost++; wlan_handle_disconnect_event(pmpriv); break; case EVENT_PS_SLEEP: PRINTM(MINFO, "EVENT: SLEEP\n"); PRINTM(MEVENT, "_"); /* Handle unexpected PS SLEEP event */ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) break; pmadapter->ps_state = PS_STATE_PRE_SLEEP; wlan_check_ps_cond(pmadapter); break; case EVENT_PS_AWAKE: PRINTM(MINFO, "EVENT: AWAKE\n"); PRINTM(MEVENT, "|"); if (!pmadapter->pps_uapsd_mode && pmpriv->media_connected && (pmpriv->port_open || !pmpriv->port_ctrl_mode) && pmadapter->sleep_period.period) { pmadapter->pps_uapsd_mode = MTRUE; PRINTM(MEVENT, "PPS/UAPSD mode activated\n"); } /* Handle unexpected PS AWAKE event */ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) break; pmadapter->tx_lock_flag = MFALSE; if (pmadapter->pps_uapsd_mode && pmadapter->gen_null_pkt) { if (MTRUE == wlan_check_last_packet_indication(pmpriv)) { if (!pmadapter->data_sent) { if (wlan_send_null_packet(pmpriv, MRVDRV_TxPD_POWER_MGMT_NULL_PACKET | MRVDRV_TxPD_POWER_MGMT_LAST_PACKET) == MLAN_STATUS_SUCCESS) { LEAVE(); return MLAN_STATUS_SUCCESS; } } } } pmadapter->ps_state = PS_STATE_AWAKE; pmadapter->pm_wakeup_card_req = MFALSE; pmadapter->pm_wakeup_fw_try = MFALSE; break; case EVENT_HS_ACT_REQ: PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n"); ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, 0, 0, MNULL, MNULL); break; case EVENT_MIC_ERR_UNICAST: PRINTM(MEVENT, "EVENT: UNICAST MIC ERROR\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_UNI, MNULL); break; case EVENT_MIC_ERR_MULTICAST: PRINTM(MEVENT, "EVENT: MULTICAST MIC ERROR\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_MUL, MNULL); break; case EVENT_MIB_CHANGED: case EVENT_INIT_DONE: break; case EVENT_ADHOC_BCN_LOST: PRINTM(MEVENT, "EVENT: ADHOC_BCN_LOST\n"); pmpriv->adhoc_is_link_sensed = MFALSE; wlan_clean_txrx(pmpriv); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_LOST, MNULL); break; case EVENT_FW_DEBUG_INFO: /* Allocate memory for event buffer */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf); if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) { pevent = (pmlan_event)evt_buf; pevent->bss_index = pmpriv->bss_index; PRINTM(MEVENT, "EVENT: FW Debug Info\n"); pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO; pevent->event_len = pmbuf->data_len - sizeof(eventcause); memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause), pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf); } break; case EVENT_BG_SCAN_REPORT: PRINTM(MEVENT, "EVENT: BGS_REPORT\n"); pmadapter->bgscan_reported = MTRUE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN, MNULL); break; case EVENT_BG_SCAN_STOPPED: PRINTM(MEVENT, "EVENT: BGS_STOPPED\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN_STOPPED, MNULL); break; case EVENT_PORT_RELEASE: PRINTM(MEVENT, "EVENT: PORT RELEASE\n"); /* Open the port for e-supp mode */ if (pmpriv->port_ctrl_mode == MTRUE) { PRINTM(MINFO, "PORT_REL: port_status = OPEN\n"); pmpriv->port_open = MTRUE; } pmadapter->scan_block = MFALSE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PORT_RELEASE, MNULL); break; case EVENT_STOP_TX: PRINTM(MEVENT, "EVENT: Stop Tx (%#x)\n", eventcause); wlan_11h_tx_disable(pmpriv); /* this fn will send event up to MOAL */ break; case EVENT_START_TX: PRINTM(MEVENT, "EVENT: Start Tx (%#x)\n", eventcause); wlan_11h_tx_enable(pmpriv); /* this fn will send event up to MOAL */ break; case EVENT_CHANNEL_SWITCH: PRINTM(MEVENT, "EVENT: Channel Switch (%#x)\n", eventcause); /* To be handled for 'chanswann' private command */ break; case EVENT_CHANNEL_SWITCH_ANN: PRINTM(MEVENT, "EVENT: Channel Switch Announcement\n"); /* Here, pass up event first, as handling will send deauth */ wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN, MNULL); wlan_11h_handle_event_chanswann(pmpriv); break; case EVENT_RADAR_DETECTED: PRINTM(MEVENT, "EVENT: Radar Detected\n"); /* Send as passthru first, this event can cause other events */ memset(pmadapter, pevent, 0x00, sizeof(event_buf)); pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); if (pmadapter->state_rdh.stage == RDH_OFF) { pmadapter->state_rdh.stage = RDH_CHK_INTFS; wlan_11h_radar_detected_handling(pmadapter); } else { PRINTM(MEVENT, "Ignore Event Radar Detected - handling" " already in progress.\n"); } break; case EVENT_CHANNEL_REPORT_RDY: PRINTM(MEVENT, "EVENT: Channel Report Ready\n"); /* Allocate memory for event buffer */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf); if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) { memset(pmadapter, evt_buf, 0x00, MAX_EVENT_SIZE); /* Setup event buffer */ pevent = (pmlan_event)evt_buf; pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY; pevent->event_len = pmbuf->data_len - sizeof(eventcause); /* Copy event data */ memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause), pevent->event_len); /* Handle / pass event data */ ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent); /* Also send this event as passthru */ pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); /* Now done with buffer */ pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf); } /* Send up this Event to unblock MOAL waitqueue */ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL); break; case EVENT_EXT_SCAN_REPORT: PRINTM(MEVENT, "EVENT: EXT_SCAN Report (%d)\n", pmbuf->data_len); if (pmadapter->pscan_ioctl_req && pmadapter->ext_scan) ret = wlan_handle_event_ext_scan_report(priv, pmbuf); break; case EVENT_MEAS_REPORT_RDY: PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n", eventcause); ret = wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT, HostCmd_ACT_GEN_SET, 0, 0, MNULL); break; case EVENT_WMM_STATUS_CHANGE: if (pmbuf && pmbuf->data_len > sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) { PRINTM(MEVENT, "EVENT: WMM status changed: %d\n", pmbuf->data_len); evt_buf = (pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)); wlan_ret_wmm_get_status(pmpriv, evt_buf, pmbuf->data_len - sizeof(eventcause)); } else { PRINTM(MEVENT, "EVENT: WMM status changed\n"); ret = wlan_cmd_wmm_status_change(pmpriv); } break; case EVENT_RSSI_LOW: PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_RSSI_LOW, MNULL); break; case EVENT_SNR_LOW: PRINTM(MEVENT, "EVENT: Beacon SNR_LOW\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_LOW, MNULL); break; case EVENT_MAX_FAIL: PRINTM(MEVENT, "EVENT: MAX_FAIL\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MAX_FAIL, MNULL); break; case EVENT_RSSI_HIGH: PRINTM(MEVENT, "EVENT: Beacon RSSI_HIGH\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_RSSI_HIGH, MNULL); break; case EVENT_SNR_HIGH: PRINTM(MEVENT, "EVENT: Beacon SNR_HIGH\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_HIGH, MNULL); break; case EVENT_DATA_RSSI_LOW: PRINTM(MEVENT, "EVENT: Data RSSI_LOW\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_LOW, MNULL); break; case EVENT_DATA_SNR_LOW: PRINTM(MEVENT, "EVENT: Data SNR_LOW\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_LOW, MNULL); break; case EVENT_DATA_RSSI_HIGH: PRINTM(MEVENT, "EVENT: Data RSSI_HIGH\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, MNULL); break; case EVENT_DATA_SNR_HIGH: PRINTM(MEVENT, "EVENT: Data SNR_HIGH\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_HIGH, MNULL); break; case EVENT_LINK_QUALITY: PRINTM(MEVENT, "EVENT: Link Quality\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_LINK_QUALITY, MNULL); break; case EVENT_PRE_BEACON_LOST: PRINTM(MEVENT, "EVENT: Pre-Beacon Lost\n"); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PRE_BCN_LOST, MNULL); break; case EVENT_IBSS_COALESCED: PRINTM(MEVENT, "EVENT: IBSS_COALESCED\n"); ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, HostCmd_ACT_GEN_GET, 0, MNULL, MNULL); break; case EVENT_ADDBA: PRINTM(MEVENT, "EVENT: ADDBA Request\n"); if (pmpriv->media_connected == MTRUE) ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11N_ADDBA_RSP, HostCmd_ACT_GEN_SET, 0, MNULL, pmadapter->event_body); else PRINTM(MERROR, "Ignore ADDBA Request event in disconnected state\n"); break; case EVENT_DELBA: PRINTM(MEVENT, "EVENT: DELBA Request\n"); if (pmpriv->media_connected == MTRUE) wlan_11n_delete_bastream(pmpriv, pmadapter->event_body); else PRINTM(MERROR, "Ignore DELBA Request event in disconnected state\n"); break; case EVENT_BA_STREAM_TIMEOUT: PRINTM(MEVENT, "EVENT: BA Stream timeout\n"); if (pmpriv->media_connected == MTRUE) wlan_11n_ba_stream_timeout(pmpriv, (HostCmd_DS_11N_BATIMEOUT *) pmadapter->event_body); else PRINTM(MERROR, "Ignore BA Stream timeout event in disconnected state\n"); break; case EVENT_RXBA_SYNC: PRINTM(MEVENT, "EVENT: RXBA_SYNC\n"); wlan_11n_rxba_sync_event(pmpriv, pmadapter->event_body, pmbuf->data_len - sizeof(eventcause)); break; case EVENT_AMSDU_AGGR_CTRL: PRINTM(MEVENT, "EVENT: AMSDU_AGGR_CTRL %d\n", *(t_u16 *)pmadapter->event_body); pmadapter->tx_buf_size = MIN(pmadapter->curr_tx_buf_size, wlan_le16_to_cpu(*(t_u16 *)pmadapter->event_body)); PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size); break; case EVENT_WEP_ICV_ERR: PRINTM(MEVENT, "EVENT: WEP ICV error\n"); pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_WEP_ICV_ERR; pevent->event_len = sizeof(Event_WEP_ICV_ERR); memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmadapter->event_body, pevent->event_len); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_WEP_ICV_ERR, pevent); break; case EVENT_BW_CHANGE: PRINTM(MEVENT, "EVENT: BW Change\n"); pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_BW_CHANGED; pevent->event_len = sizeof(t_u8); /* Copy event body from the event buffer */ memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmadapter->event_body, pevent->event_len); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BW_CHANGED, pevent); break; #ifdef WIFI_DIRECT_SUPPORT case EVENT_WIFIDIRECT_GENERIC_EVENT: PRINTM(MEVENT, "EVENT: WIFIDIRECT event %d\n", eventcause); /* Allocate memory for event buffer */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf); if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) { pevent = (pmlan_event)evt_buf; pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf); } break; case EVENT_WIFIDIRECT_SERVICE_DISCOVERY: PRINTM(MEVENT, "EVENT: WIFIDIRECT service discovery event %d\n", eventcause); /* Allocate large memory for service discovery */ if (pmbuf->data_len < MAX_EVENT_SIZE) ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf); else ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE * 2, MLAN_MEM_DEF, &evt_buf); if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) { pevent = (pmlan_event)evt_buf; pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf); } break; case EVENT_REMAIN_ON_CHANNEL_EXPIRED: PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n", *(t_u16 *)pmadapter->event_body); wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED, MNULL); break; #endif /* WIFI_DIRECT_SUPPORT */ case EVENT_TDLS_GENERIC_EVENT: PRINTM(MEVENT, "EVENT: TDLS event %d\n", eventcause); wlan_parse_tdls_event(pmpriv, pmbuf); /* Allocate memory for event buffer */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf); if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) { pevent = (pmlan_event)evt_buf; pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf); } break; case EVENT_TX_DATA_PAUSE: PRINTM(MEVENT, "EVENT: TX_DATA_PAUSE\n"); wlan_process_sta_tx_pause_event(priv, pmbuf); break; case EVENT_SAD_REPORT: pevent->event_len = pmbuf->data_len - sizeof(eventcause); if (pevent->event_len > sizeof(t_u32)) { PRINTM(MEVENT, "EVENT: SAD_REPORT %d\n", eventcause); /* Allocate memory for event buffer */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf); if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) { pevent = (pmlan_event)evt_buf; pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf); } } else { t_u8 *pevt_dat = pmbuf->pbuf + pmbuf->data_offset + sizeof(t_u32); PRINTM(MEVENT, "EVENT: Antenna Diversity %d (%d, %d, %d, %d)\n", eventcause, pevt_dat[0] + 1, pevt_dat[1] + 1, pevt_dat[2], pevt_dat[3]); } break; case EVENT_MULTI_CHAN_INFO: PRINTM(MEVENT, "EVENT: MULTI_CHAN_INFO\n"); wlan_handle_event_multi_chan_info(pmpriv, pmbuf); break; case EVENT_FW_DUMP_INFO: PRINTM(MEVENT, "EVENT: Dump FW info\n"); /* Allocate memory for event buffer */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf); if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) { pevent = (pmlan_event)evt_buf; pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_DUMP_INFO; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf); } break; case EVENT_TX_STATUS_REPORT: PRINTM(MINFO, "EVENT: TX_STATUS\n"); pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_TX_STATUS; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, MIN(pevent->event_len, sizeof (event_buf))); wlan_recv_event(pmpriv, pevent->event_id, pevent); break; case EVENT_BT_COEX_WLAN_PARA_CHANGE: PRINTM(MEVENT, "EVENT: BT coex wlan param update\n"); wlan_bt_coex_wlan_param_update_event(pmpriv, pmbuf); break; default: PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL); break; } LEAVE(); return ret; }