Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_rm.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/1415#include <drv_types.h>16#include <hal_data.h>17#ifdef CONFIG_RTW_80211K18#include "rtw_rm_fsm.h"19#include "rtw_rm_util.h"20#endif2122#define pstr(s) s+strlen(s)2324u8 rm_post_event_hdl(_adapter *padapter, u8 *pbuf)25{26#ifdef CONFIG_RTW_80211K27struct rm_event *pev = (struct rm_event *)pbuf;2829_rm_post_event(padapter, pev->rmid, pev->evid);30rm_handler(padapter, pev);31#endif32return H2C_SUCCESS;33}3435#ifdef CONFIG_RTW_80211K36struct cmd_meas_type_ {37u8 id;38char *name;39};4041char *rm_type_req_name(u8 meas_type) {4243switch (meas_type) {44case basic_req:45return "basic_req";46case cca_req:47return "cca_req";48case rpi_histo_req:49return "rpi_histo_req";50case ch_load_req:51return "ch_load_req";52case noise_histo_req:53return "noise_histo_req";54case bcn_req:55return "bcn_req";56case frame_req:57return "frame_req";58case sta_statis_req:59return "sta_statis_req";60}61return "unknown_req";62};6364char *rm_type_rep_name(u8 meas_type) {6566switch (meas_type) {67case basic_rep:68return "basic_rep";69case cca_rep:70return "cca_rep";71case rpi_histo_rep:72return "rpi_histo_rep";73case ch_load_rep:74return "ch_load_rep";75case noise_histo_rep:76return "noise_histo_rep";77case bcn_rep:78return "bcn_rep";79case frame_rep:80return "frame_rep";81case sta_statis_rep:82return "sta_statis_rep";83}84return "unknown_rep";85};8687char *rm_en_cap_name(enum rm_cap_en en)88{89switch (en) {90case RM_LINK_MEAS_CAP_EN:91return "RM_LINK_MEAS_CAP_EN";92case RM_NB_REP_CAP_EN:93return "RM_NB_REP_CAP_EN";94case RM_PARAL_MEAS_CAP_EN:95return "RM_PARAL_MEAS_CAP_EN";96case RM_REPEAT_MEAS_CAP_EN:97return "RM_REPEAT_MEAS_CAP_EN";98case RM_BCN_PASSIVE_MEAS_CAP_EN:99return "RM_BCN_PASSIVE_MEAS_CAP_EN";100case RM_BCN_ACTIVE_MEAS_CAP_EN:101return "RM_BCN_ACTIVE_MEAS_CAP_EN";102case RM_BCN_TABLE_MEAS_CAP_EN:103return "RM_BCN_TABLE_MEAS_CAP_EN";104case RM_BCN_MEAS_REP_COND_CAP_EN:105return "RM_BCN_MEAS_REP_COND_CAP_EN";106107case RM_FRAME_MEAS_CAP_EN:108return "RM_FRAME_MEAS_CAP_EN";109case RM_CH_LOAD_CAP_EN:110return "RM_CH_LOAD_CAP_EN";111case RM_NOISE_HISTO_CAP_EN:112return "RM_NOISE_HISTO_CAP_EN";113case RM_STATIS_MEAS_CAP_EN:114return "RM_STATIS_MEAS_CAP_EN";115case RM_LCI_MEAS_CAP_EN:116return "RM_LCI_MEAS_CAP_EN";117case RM_LCI_AMIMUTH_CAP_EN:118return "RM_LCI_AMIMUTH_CAP_EN";119case RM_TRANS_STREAM_CAT_MEAS_CAP_EN:120return "RM_TRANS_STREAM_CAT_MEAS_CAP_EN";121case RM_TRIG_TRANS_STREAM_CAT_MEAS_CAP_EN:122return "RM_TRIG_TRANS_STREAM_CAT_MEAS_CAP_EN";123124case RM_AP_CH_REP_CAP_EN:125return "RM_AP_CH_REP_CAP_EN";126case RM_RM_MIB_CAP_EN:127return "RM_RM_MIB_CAP_EN";128case RM_OP_CH_MAX_MEAS_DUR0:129return "RM_OP_CH_MAX_MEAS_DUR0";130case RM_OP_CH_MAX_MEAS_DUR1:131return "RM_OP_CH_MAX_MEAS_DUR1";132case RM_OP_CH_MAX_MEAS_DUR2:133return "RM_OP_CH_MAX_MEAS_DUR2";134case RM_NONOP_CH_MAX_MEAS_DUR0:135return "RM_NONOP_CH_MAX_MEAS_DUR0";136case RM_NONOP_CH_MAX_MEAS_DUR1:137return "RM_NONOP_CH_MAX_MEAS_DUR1";138case RM_NONOP_CH_MAX_MEAS_DUR2:139return "RM_NONOP_CH_MAX_MEAS_DUR2";140141case RM_MEAS_PILOT_CAP0:142return "RM_MEAS_PILOT_CAP0"; /* 24-26 */143case RM_MEAS_PILOT_CAP1:144return "RM_MEAS_PILOT_CAP1";145case RM_MEAS_PILOT_CAP2:146return "RM_MEAS_PILOT_CAP2";147case RM_MEAS_PILOT_TRANS_INFO_CAP_EN:148return "RM_MEAS_PILOT_TRANS_INFO_CAP_EN";149case RM_NB_REP_TSF_OFFSET_CAP_EN:150return "RM_NB_REP_TSF_OFFSET_CAP_EN";151case RM_RCPI_MEAS_CAP_EN:152return "RM_RCPI_MEAS_CAP_EN"; /* 29 */153case RM_RSNI_MEAS_CAP_EN:154return "RM_RSNI_MEAS_CAP_EN";155case RM_BSS_AVG_ACCESS_DELAY_CAP_EN:156return "RM_BSS_AVG_ACCESS_DELAY_CAP_EN";157158case RM_AVALB_ADMIS_CAPACITY_CAP_EN:159return "RM_AVALB_ADMIS_CAPACITY_CAP_EN";160case RM_ANT_CAP_EN:161return "RM_ANT_CAP_EN";162case RM_RSVD:163case RM_MAX:164default:165break;166}167return "unknown";168}169170int rm_en_cap_chk_and_set(struct rm_obj *prm, enum rm_cap_en en)171{172int idx;173u8 cap;174175176if (en >= RM_MAX)177return _FALSE;178179idx = en / 8;180cap = prm->psta->padapter->rmpriv.rm_en_cap_def[idx];181182if (!(cap & BIT(en - (idx*8)))) {183RTW_INFO("RM: %s incapable\n",rm_en_cap_name(en));184rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);185return _FALSE;186}187return _SUCCESS;188}189190/* for caller outside rm */191u8 rm_add_nb_req(_adapter *padapter, struct sta_info *psta)192{193struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;194struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;195struct rm_obj *prm;196197198prm = rm_alloc_rmobj(padapter);199200if (prm == NULL) {201RTW_ERR("RM: unable to alloc rm obj for requeset\n");202return _FALSE;203}204205prm->psta = psta;206prm->q.category = RTW_WLAN_CATEGORY_RADIO_MEAS;207do {208pmlmeinfo->dialogToken++;209} while (pmlmeinfo->dialogToken == 0);210211prm->q.diag_token = pmlmeinfo->dialogToken;212prm->q.m_token = 1;213214prm->rmid = psta->cmn.aid << 16215| prm->q.diag_token << 8216| RM_MASTER;217218prm->q.action_code = RM_ACT_NB_REP_REQ;219220#if 0221if (pmac) { /* find sta_info according to bssid */222pmac += 4; /* skip mac= */223if (hwaddr_parse(pmac, bssid) == NULL) {224sprintf(pstr(s), "Err: \nincorrect mac format\n");225return _FAIL;226}227psta = rm_get_sta(padapter, 0xff, bssid);228}229#endif230231/* enquee rmobj */232rm_enqueue_rmobj(padapter, prm, _FALSE);233234RTW_INFO("RM: rmid=%x add req to " MAC_FMT "\n",235prm->rmid, MAC_ARG(psta->cmn.mac_addr));236237return _SUCCESS;238}239240static u8 *build_wlan_hdr(_adapter *padapter, struct xmit_frame *pmgntframe,241struct sta_info *psta, u16 frame_type)242{243u8 *pframe;244u16 *fctrl;245struct pkt_attrib *pattr;246struct rtw_ieee80211_hdr *pwlanhdr;247struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;248struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;249250251/* update attribute */252pattr = &pmgntframe->attrib;253update_mgntframe_attrib(padapter, pattr);254255_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);256257pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;258pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;259260fctrl = &(pwlanhdr->frame_ctl);261*(fctrl) = 0;262263_rtw_memcpy(pwlanhdr->addr1, psta->cmn.mac_addr, ETH_ALEN);264_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);265_rtw_memcpy(pwlanhdr->addr3,266get_my_bssid(&(pmlmeinfo->network)),ETH_ALEN);267268RTW_INFO("RM: dst = " MAC_FMT "\n", MAC_ARG(pwlanhdr->addr1));269270SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);271pmlmeext->mgnt_seq++;272SetFragNum(pframe, 0);273274set_frame_sub_type(pframe, WIFI_ACTION);275276pframe += sizeof(struct rtw_ieee80211_hdr_3addr);277pattr->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);278279return pframe;280}281282void rm_set_rep_mode(struct rm_obj *prm, u8 mode)283{284285RTW_INFO("RM: rmid=%x set %s\n",286prm->rmid,287mode|MEAS_REP_MOD_INCAP?"INCAP":288mode|MEAS_REP_MOD_REFUSE?"REFUSE":289mode|MEAS_REP_MOD_LATE?"LATE":"");290291prm->p.m_mode |= mode;292}293294int issue_null_reply(struct rm_obj *prm)295{296int len=0, my_len;297u8 *pframe, m_mode;298_adapter *padapter = prm->psta->padapter;299struct pkt_attrib *pattr;300struct xmit_frame *pmgntframe;301struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);302303304m_mode = prm->p.m_mode;305if (m_mode || prm->p.rpt == 0) {306RTW_INFO("RM: rmid=%x reply (%s repeat=%d)\n",307prm->rmid,308m_mode&MEAS_REP_MOD_INCAP?"INCAP":309m_mode&MEAS_REP_MOD_REFUSE?"REFUSE":310m_mode&MEAS_REP_MOD_LATE?"LATE":"no content",311prm->p.rpt);312}313314switch (prm->p.action_code) {315case RM_ACT_RADIO_MEAS_REQ:316len = 8;317break;318case RM_ACT_NB_REP_REQ:319len = 3;320break;321case RM_ACT_LINK_MEAS_REQ:322len = 3;323break;324default:325break;326}327328if (len==0)329return _FALSE;330331pmgntframe = alloc_mgtxmitframe(pxmitpriv);332if (pmgntframe == NULL) {333RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);334return _FALSE;335}336pattr = &pmgntframe->attrib;337pframe = build_wlan_hdr(padapter, pmgntframe, prm->psta, WIFI_ACTION);338pframe = rtw_set_fixed_ie(pframe, 3, &prm->p.category, &pattr->pktlen);339340my_len = 0;341if (len>5) {342prm->p.len = len - 3 - 2;343pframe = rtw_set_fixed_ie(pframe, len - 3,344&prm->p.e_id, &my_len);345}346347pattr->pktlen += my_len;348pattr->last_txcmdsz = pattr->pktlen;349dump_mgntframe(padapter, pmgntframe);350351return _SUCCESS;352}353354int ready_for_scan(struct rm_obj *prm)355{356_adapter *padapter = prm->psta->padapter;357u8 ssc_chk;358359if (!rtw_is_adapter_up(padapter))360return _FALSE;361362ssc_chk = rtw_sitesurvey_condition_check(padapter, _FALSE);363364if (ssc_chk == SS_ALLOW)365return _SUCCESS;366367return _FALSE;368}369370int rm_sitesurvey(struct rm_obj *prm)371{372int meas_ch_num=0;373u8 ch_num=0, op_class=0, val8;374struct rtw_ieee80211_channel *pch_set;375struct sitesurvey_parm parm;376377378RTW_INFO("RM: rmid=%x %s\n",prm->rmid, __func__);379380pch_set = &prm->q.ch_set[0];381382_rtw_memset(pch_set, 0,383sizeof(struct rtw_ieee80211_channel) * MAX_OP_CHANNEL_SET_NUM);384385if (prm->q.ch_num == 0) {386/* ch_num=0 : scan all ch in operating class */387op_class = prm->q.op_class;388389} else if (prm->q.ch_num == 255) {390/* 802.11 p.499 */391/* ch_num=255 : scan all ch in current operating class */392op_class = rm_get_oper_class_via_ch(393(u8)prm->psta->padapter->mlmeextpriv.cur_channel);394} else395ch_num = prm->q.ch_num;396397/* get means channel */398meas_ch_num = rm_get_ch_set(pch_set, op_class, ch_num);399prm->q.ch_set_ch_amount = meas_ch_num;400401_rtw_memset(&parm, 0, sizeof(struct sitesurvey_parm));402_rtw_memcpy(parm.ch, pch_set,403sizeof(struct rtw_ieee80211_channel) * MAX_OP_CHANNEL_SET_NUM);404405_rtw_memcpy(&parm.ssid[0], &prm->q.opt.bcn.ssid, IW_ESSID_MAX_SIZE);406407parm.ssid_num = 1;408parm.scan_mode = prm->q.m_mode;409parm.ch_num = meas_ch_num;410parm.igi = 0;411parm.token = prm->rmid;412parm.duration = prm->q.meas_dur;413/* parm.bw = BW_20M; */414415rtw_sitesurvey_cmd(prm->psta->padapter, &parm);416417return _SUCCESS;418}419420static int rm_parse_ch_load_s_elem(struct rm_obj *prm, u8 *pbody, int req_len)421{422u8 *popt_id;423int i, p=0; /* position */424int len = req_len;425426427prm->q.opt_s_elem_len = len;428#if (RM_MORE_DBG_MSG)429RTW_INFO("RM: opt_s_elem_len=%d\n", len);430#endif431while (len) {432433switch (pbody[p]) {434case ch_load_rep_info:435/* check RM_EN */436rm_en_cap_chk_and_set(prm, RM_CH_LOAD_CAP_EN);437438_rtw_memcpy(&(prm->q.opt.clm.rep_cond),439&pbody[p+2], sizeof(prm->q.opt.clm.rep_cond));440441RTW_INFO("RM: ch_load_rep_info=%u:%u\n",442prm->q.opt.clm.rep_cond.cond,443prm->q.opt.clm.rep_cond.threshold);444break;445default:446break;447448}449len = len - (int)pbody[p+1] - 2;450p = p + (int)pbody[p+1] + 2;451#if (RM_MORE_DBG_MSG)452RTW_INFO("RM: opt_s_elem_len=%d\n",len);453#endif454}455return _SUCCESS;456}457458static int rm_parse_noise_histo_s_elem(struct rm_obj *prm,459u8 *pbody, int req_len)460{461u8 *popt_id;462int i, p=0; /* position */463int len = req_len;464465466prm->q.opt_s_elem_len = len;467#if (RM_MORE_DBG_MSG)468RTW_INFO("RM: opt_s_elem_len=%d\n", len);469#endif470471while (len) {472473switch (pbody[p]) {474case noise_histo_rep_info:475/* check RM_EN */476rm_en_cap_chk_and_set(prm, RM_NOISE_HISTO_CAP_EN);477478_rtw_memcpy(&(prm->q.opt.nhm.rep_cond),479&pbody[p+2], sizeof(prm->q.opt.nhm.rep_cond));480481RTW_INFO("RM: noise_histo_rep_info=%u:%u\n",482prm->q.opt.nhm.rep_cond.cond,483prm->q.opt.nhm.rep_cond.threshold);484break;485default:486break;487488}489len = len - (int)pbody[p+1] - 2;490p = p + (int)pbody[p+1] + 2;491#if (RM_MORE_DBG_MSG)492RTW_INFO("RM: opt_s_elem_len=%d\n",len);493#endif494}495return _SUCCESS;496}497498static int rm_parse_bcn_req_s_elem(struct rm_obj *prm, u8 *pbody, int req_len)499{500u8 *popt_id;501int i, p=0; /* position */502int len = req_len;503504505/* opt length,2:pbody[0]+ pbody[1] */506/* first opt id : pbody[18] */507508prm->q.opt_s_elem_len = len;509#if (RM_MORE_DBG_MSG)510RTW_INFO("RM: opt_s_elem_len=%d\n", len);511#endif512513popt_id = prm->q.opt.bcn.opt_id;514while (len && prm->q.opt.bcn.opt_id_num < BCN_REQ_OPT_MAX_NUM) {515516switch (pbody[p]) {517case bcn_req_ssid:518RTW_INFO("bcn_req_ssid\n");519520#if (DBG_BCN_REQ_WILDCARD)521RTW_INFO("DBG set ssid to WILDCARD\n");522#else523#if (DBG_BCN_REQ_SSID)524RTW_INFO("DBG set ssid to %s\n",DBG_BCN_REQ_SSID_NAME);525i = strlen(DBG_BCN_REQ_SSID_NAME);526prm->q.opt.bcn.ssid.SsidLength = i;527_rtw_memcpy(&(prm->q.opt.bcn.ssid.Ssid),528DBG_BCN_REQ_SSID_NAME, i);529530#else /* original */531prm->q.opt.bcn.ssid.SsidLength = pbody[p+1];532_rtw_memcpy(&(prm->q.opt.bcn.ssid.Ssid),533&pbody[p+2], pbody[p+1]);534#endif535#endif536537RTW_INFO("RM: bcn_req_ssid=%s\n",538prm->q.opt.bcn.ssid.Ssid);539540popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];541break;542543case bcn_req_rep_info:544/* check RM_EN */545rm_en_cap_chk_and_set(prm, RM_BCN_MEAS_REP_COND_CAP_EN);546547_rtw_memcpy(&(prm->q.opt.bcn.rep_cond),548&pbody[p+2], sizeof(prm->q.opt.bcn.rep_cond));549550RTW_INFO("bcn_req_rep_info=%u:%u\n",551prm->q.opt.bcn.rep_cond.cond,552prm->q.opt.bcn.rep_cond.threshold);553554/*popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];*/555break;556557case bcn_req_rep_detail:558#if DBG_BCN_REQ_DETAIL559prm->q.opt.bcn.rep_detail = 2; /* all IE in beacon */560#else561prm->q.opt.bcn.rep_detail = pbody[p+2];562#endif563popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];564565#if (RM_MORE_DBG_MSG)566RTW_INFO("RM: report_detail=%d\n",567prm->q.opt.bcn.rep_detail);568#endif569break;570571case bcn_req_req:572RTW_INFO("RM: bcn_req_req\n");573574prm->q.opt.bcn.req_start = rtw_malloc(pbody[p+1]);575576if (prm->q.opt.bcn.req_start == NULL) {577RTW_ERR("RM: req_start malloc fail!!\n");578break;579}580581for (i = 0; i < pbody[p+1]; i++)582*((prm->q.opt.bcn.req_start)+i) =583pbody[p+2+i];584585prm->q.opt.bcn.req_len = pbody[p+1];586popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];587break;588589case bcn_req_ac_ch_rep:590#if (RM_MORE_DBG_MSG)591RTW_INFO("RM: bcn_req_ac_ch_rep\n");592#endif593popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];594break;595596default:597break;598599}600len = len - (int)pbody[p+1] - 2;601p = p + (int)pbody[p+1] + 2;602#if (RM_MORE_DBG_MSG)603RTW_INFO("RM: opt_s_elem_len=%d\n",len);604#endif605}606607return _SUCCESS;608}609610static int rm_parse_meas_req(struct rm_obj *prm, u8 *pbody)611{612int p; /* position */613int req_len;614615616req_len = (int)pbody[1];617p = 5;618619prm->q.op_class = pbody[p++];620prm->q.ch_num = pbody[p++];621prm->q.rand_intvl = le16_to_cpu(*(u16*)(&pbody[p]));622p+=2;623prm->q.meas_dur = le16_to_cpu(*(u16*)(&pbody[p]));624p+=2;625626if (prm->q.m_type == bcn_req) {627/*628* 0: passive629* 1: active630* 2: bcn_table631*/632prm->q.m_mode = pbody[p++];633634/* BSSID */635_rtw_memcpy(&(prm->q.bssid), &pbody[p], 6);636p+=6;637638/*639* default, used when Reporting detail subelement640* is not included in Beacon Request641*/642prm->q.opt.bcn.rep_detail = 2;643}644645if (req_len-(p-2) <= 0) /* without sub-element */646return _SUCCESS;647648switch (prm->q.m_type) {649case bcn_req:650rm_parse_bcn_req_s_elem(prm, &pbody[p], req_len-(p-2));651break;652case ch_load_req:653rm_parse_ch_load_s_elem(prm, &pbody[p], req_len-(p-2));654break;655case noise_histo_req:656rm_parse_noise_histo_s_elem(prm, &pbody[p], req_len-(p-2));657break;658default:659break;660}661662return _SUCCESS;663}664665/* receive measurement request */666int rm_recv_radio_mens_req(_adapter *padapter,667union recv_frame *precv_frame, struct sta_info *psta)668{669struct rm_obj *prm;670struct rm_priv *prmpriv = &padapter->rmpriv;671u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +672sizeof(struct rtw_ieee80211_hdr_3addr));673u8 *pmeas_body = &pdiag_body[5];674u8 rmid, update = 0;675676677#if 0678/* search existing rm_obj */679rmid = psta->cmn.aid << 16680| pdiag_body[2] << 8681| RM_SLAVE;682683prm = rm_get_rmobj(padapter, rmid);684if (prm) {685RTW_INFO("RM: Found an exist meas rmid=%u\n", rmid);686update = 1;687} else688#endif689prm = rm_alloc_rmobj(padapter);690691if (prm == NULL) {692RTW_ERR("RM: unable to alloc rm obj for requeset\n");693return _FALSE;694}695696prm->psta = psta;697prm->q.diag_token = pdiag_body[2];698prm->q.rpt = le16_to_cpu(*(u16*)(&pdiag_body[3]));699700/* Figure 8-104 Measurement Requested format */701prm->q.e_id = pmeas_body[0];702prm->q.m_token = pmeas_body[2];703prm->q.m_mode = pmeas_body[3];704prm->q.m_type = pmeas_body[4];705706prm->rmid = psta->cmn.aid << 16707| prm->q.diag_token << 8708| RM_SLAVE;709710RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,711MAC_ARG(prm->psta->cmn.mac_addr));712713#if (RM_MORE_DBG_MSG)714RTW_INFO("RM: element_id = %d\n", prm->q.e_id);715RTW_INFO("RM: length = %d\n", (int)pmeas_body[1]);716RTW_INFO("RM: meas_token = %d\n", prm->q.m_token);717RTW_INFO("RM: meas_mode = %d\n", prm->q.m_mode);718RTW_INFO("RM: meas_type = %d\n", prm->q.m_type);719#endif720721if (prm->q.e_id != _MEAS_REQ_IE_) /* 38 */722return _FALSE;723724switch (prm->q.m_type) {725case bcn_req:726RTW_INFO("RM: recv beacon_request\n");727switch (prm->q.m_mode) {728case bcn_req_passive:729rm_en_cap_chk_and_set(prm, RM_BCN_PASSIVE_MEAS_CAP_EN);730break;731case bcn_req_active:732rm_en_cap_chk_and_set(prm, RM_BCN_ACTIVE_MEAS_CAP_EN);733break;734case bcn_req_bcn_table:735rm_en_cap_chk_and_set(prm, RM_BCN_TABLE_MEAS_CAP_EN);736break;737default:738rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);739break;740}741break;742case ch_load_req:743RTW_INFO("RM: recv ch_load_request\n");744rm_en_cap_chk_and_set(prm, RM_CH_LOAD_CAP_EN);745break;746case noise_histo_req:747RTW_INFO("RM: recv noise_histogram_request\n");748rm_en_cap_chk_and_set(prm, RM_NOISE_HISTO_CAP_EN);749break;750default:751RTW_INFO("RM: recv unknown request type 0x%02x\n",752prm->q.m_type);753rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);754goto done;755}756rm_parse_meas_req(prm, pmeas_body);757done:758if (!update)759rm_enqueue_rmobj(padapter, prm, _FALSE);760761return _SUCCESS;762}763764/* receive measurement report */765int rm_recv_radio_mens_rep(_adapter *padapter,766union recv_frame *precv_frame, struct sta_info *psta)767{768int ret = _FALSE;769struct rm_obj *prm;770u32 rmid;771u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +772sizeof(struct rtw_ieee80211_hdr_3addr));773u8 *pmeas_body = &pdiag_body[3];774775776rmid = psta->cmn.aid << 16777| pdiag_body[2] << 8778| RM_MASTER;779780prm = rm_get_rmobj(padapter, rmid);781if (prm == NULL)782return _FALSE;783784prm->p.action_code = pdiag_body[1];785prm->p.diag_token = pdiag_body[2];786787/* Figure 8-140 Measuremnt Report format */788prm->p.e_id = pmeas_body[0];789prm->p.m_token = pmeas_body[2];790prm->p.m_mode = pmeas_body[3];791prm->p.m_type = pmeas_body[4];792793RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,794MAC_ARG(prm->psta->cmn.mac_addr));795796#if (RM_MORE_DBG_MSG)797RTW_INFO("RM: element_id = %d\n", prm->p.e_id);798RTW_INFO("RM: length = %d\n", (int)pmeas_body[1]);799RTW_INFO("RM: meas_token = %d\n", prm->p.m_token);800RTW_INFO("RM: meas_mode = %d\n", prm->p.m_mode);801RTW_INFO("RM: meas_type = %d\n", prm->p.m_type);802#endif803if (prm->p.e_id != _MEAS_RSP_IE_) /* 39 */804return _FALSE;805806RTW_INFO("RM: recv %s\n", rm_type_rep_name(prm->p.m_type));807rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);808809return ret;810}811812/* receive link measurement request */813int rm_recv_link_mens_req(_adapter *padapter,814union recv_frame *precv_frame, struct sta_info *psta)815{816struct rm_obj *prm;817struct rm_priv *prmpriv = &padapter->rmpriv;818u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +819sizeof(struct rtw_ieee80211_hdr_3addr));820u8 *pmeas_body = &pdiag_body[3];821u8 rmid, update = 0;822int i;823824825prm = rm_alloc_rmobj(padapter);826827if (prm == NULL) {828RTW_ERR("RM: unable to alloc rm obj for requeset\n");829return _FALSE;830}831832prm->psta = psta;833prm->q.action_code = pdiag_body[1];834prm->q.diag_token = pdiag_body[2];835836prm->q.tx_pwr_used = pmeas_body[0];837prm->q.tx_pwr_max = pmeas_body[1];838prm->q.rx_pwr = precv_frame->u.hdr.attrib.phy_info.rx_power;839prm->q.rx_rate = hw_rate_to_m_rate(precv_frame->u.hdr.attrib.data_rate);840prm->q.rx_bw = precv_frame->u.hdr.attrib.bw;841prm->q.rx_rsni = rm_get_frame_rsni(prm, precv_frame);842843prm->rmid = psta->cmn.aid << 16844| prm->q.diag_token << 8845| RM_SLAVE;846847RTW_INFO("RM: rmid=%x, bssid" MAC_FMT " rx_pwr=%ddBm, rate=%s\n",848prm->rmid, MAC_ARG(prm->psta->cmn.mac_addr), prm->q.rx_pwr,849get_rate_name(prm->q.rx_rate));850851#if (RM_MORE_DBG_MSG)852RTW_INFO("RM: tx_pwr_used =%d dBm\n", prm->q.tx_pwr_used);853RTW_INFO("RM: tx_pwr_max =%d dBm\n", prm->q.tx_pwr_max);854#endif855856if (!update)857rm_enqueue_rmobj(padapter, prm, _FALSE);858859return _SUCCESS;860}861862/* receive link measurement report */863int rm_recv_link_mens_rep(_adapter *padapter,864union recv_frame *precv_frame, struct sta_info *psta)865{866int ret = _FALSE;867struct rm_obj *prm;868u32 rmid;869u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +870sizeof(struct rtw_ieee80211_hdr_3addr));871u8 *pmeas_body = pdiag_body + 3;872s8 val;873874875rmid = psta->cmn.aid << 16876| pdiag_body[2] << 8877| RM_MASTER;878879prm = rm_get_rmobj(padapter, rmid);880if (prm == NULL) {881RTW_ERR("RM: rmid 0x%08x not found\n", rmid);882return ret;883}884885RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,886MAC_ARG(prm->psta->cmn.mac_addr));887888prm->p.action_code = pdiag_body[1];889prm->p.diag_token = pdiag_body[2];890891#if (RM_MORE_DBG_MSG)892RTW_INFO("RM: action_code = %d\n", prm->p.action_code);893RTW_INFO("RM: diag_token = %d\n", prm->p.diag_token);894RTW_INFO("RM: xmit_power = %d dBm\n", pmeas_body[2]);895RTW_INFO("RM: link_margin = %d dBm\n", pmeas_body[3]);896RTW_INFO("RM: xmit_ant = %d\n", pmeas_body[4]);897RTW_INFO("RM: recv_ant = %d\n", pmeas_body[5]);898RTW_INFO("RM: RCPI = %d\n", pmeas_body[6]);899RTW_INFO("RM: RSNI = %d\n", pmeas_body[7]);900#endif901RTW_INFO("RM: recv link meas report ...\n");902ret = rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);903904return ret;905}906907908int rm_radio_mens_nb_rep(_adapter *padapter,909union recv_frame *precv_frame, struct sta_info *psta)910{911u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +912sizeof(struct rtw_ieee80211_hdr_3addr));913u8 *pmeas_body = &pdiag_body[3];914u32 len = precv_frame->u.hdr.len;915u32 rmid;916struct rm_obj *prm;917918919rmid = psta->cmn.aid << 16920| pdiag_body[2] << 8921| RM_MASTER;922923prm = rm_get_rmobj(padapter, rmid);924if (prm == NULL)925return _FALSE;926927prm->p.action_code = pdiag_body[1];928prm->p.diag_token = pdiag_body[2];929prm->p.e_id = pmeas_body[0];930931RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,932MAC_ARG(prm->psta->cmn.mac_addr));933934#if (RM_MORE_DBG_MSG)935RTW_INFO("RM: element_id = %d\n", prm->p.e_id);936RTW_INFO("RM: length = %d\n", (int)pmeas_body[1]);937#endif938rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);939940#ifdef CONFIG_LAYER2_ROAMING941if (rtw_wnm_btm_candidates_survey(padapter942,(pdiag_body + 3)943,(len - sizeof(struct rtw_ieee80211_hdr_3addr))944,_FALSE) == _FAIL)945return _FALSE;946#endif947rtw_cfg80211_rx_rrm_action(padapter, precv_frame);948949return _TRUE;950}951952unsigned int rm_on_action(_adapter *padapter, union recv_frame *precv_frame)953{954u32 ret = _FAIL;955u8 *pframe = NULL;956u8 *pframe_body = NULL;957u8 action_code = 0;958u8 diag_token = 0;959struct rtw_ieee80211_hdr_3addr *whdr;960struct sta_info *psta;961962963pframe = precv_frame->u.hdr.rx_data;964965/* check RA matches or not */966if (!_rtw_memcmp(adapter_mac_addr(padapter),967GetAddr1Ptr(pframe), ETH_ALEN))968goto exit;969970whdr = (struct rtw_ieee80211_hdr_3addr *)pframe;971RTW_INFO("RM: %s bssid = " MAC_FMT "\n",972__func__, MAC_ARG(whdr->addr2));973974psta = rtw_get_stainfo(&padapter->stapriv, whdr->addr2);975976if (!psta) {977RTW_ERR("RM: psta not found\n");978goto exit;979}980981pframe_body = (unsigned char *)(pframe +982sizeof(struct rtw_ieee80211_hdr_3addr));983984/* Figure 8-438 radio measurement request frame Action field format */985/* Category = pframe_body[0] = 5 (Radio Measurement) */986action_code = pframe_body[1];987diag_token = pframe_body[2];988989#if (RM_MORE_DBG_MSG)990RTW_INFO("RM: %s radio_action=%x, diag_token=%x\n", __func__,991action_code, diag_token);992#endif993994switch (action_code) {995996case RM_ACT_RADIO_MEAS_REQ:997RTW_INFO("RM: RM_ACT_RADIO_MEAS_REQ\n");998ret = rm_recv_radio_mens_req(padapter, precv_frame, psta);999break;10001001case RM_ACT_RADIO_MEAS_REP:1002RTW_INFO("RM: RM_ACT_RADIO_MEAS_REP\n");1003ret = rm_recv_radio_mens_rep(padapter, precv_frame, psta);1004break;10051006case RM_ACT_LINK_MEAS_REQ:1007RTW_INFO("RM: RM_ACT_LINK_MEAS_REQ\n");1008ret = rm_recv_link_mens_req(padapter, precv_frame, psta);1009break;10101011case RM_ACT_LINK_MEAS_REP:1012RTW_INFO("RM: RM_ACT_LINK_MEAS_REP\n");1013ret = rm_recv_link_mens_rep(padapter, precv_frame, psta);1014break;10151016case RM_ACT_NB_REP_REQ:1017RTW_INFO("RM: RM_ACT_NB_REP_REQ\n");1018break;10191020case RM_ACT_NB_REP_RESP:1021RTW_INFO("RM: RM_ACT_NB_REP_RESP\n");1022ret = rm_radio_mens_nb_rep(padapter, precv_frame, psta);1023break;10241025default:1026/* TODO reply incabable */1027RTW_ERR("RM: unknown specturm management action %2x\n",1028action_code);1029break;1030}1031exit:1032return ret;1033}10341035static u8 *rm_gen_bcn_detail_elem(_adapter *padapter, u8 *pframe,1036struct rm_obj *prm, struct wlan_network *pnetwork,1037unsigned int *fr_len)1038{1039WLAN_BSSID_EX *pbss = &pnetwork->network;1040unsigned int my_len;1041int j, k, len;1042u8 *plen;1043u8 *ptr;1044u8 val8, eid;104510461047my_len = 0;1048/* Reporting Detail values1049* 0: No fixed length fields or elements1050* 1: All fixed length fields and any requested elements1051* in the Request info element if present1052* 2: All fixed length fields and elements1053* 3-255: Reserved1054*/10551056/* report_detail = 0 */1057if (prm->q.opt.bcn.rep_detail == 01058|| prm->q.opt.bcn.rep_detail > 2) {1059return pframe;1060}10611062/* ID */1063val8 = 1; /* 1:reported frame body */1064pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);10651066plen = pframe;1067val8 = 0;1068pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);10691070/* report_detail = 2 */1071if (prm->q.opt.bcn.rep_detail == 2) {1072pframe = rtw_set_fixed_ie(pframe, pbss->IELength - 4,1073pbss->IEs, &my_len); /* -4 remove FCS */1074goto done;1075}10761077/* report_detail = 1 */1078/* all fixed lenght fields */1079pframe = rtw_set_fixed_ie(pframe,1080_FIXED_IE_LENGTH_, pbss->IEs, &my_len);10811082for (j = 0; j < prm->q.opt.bcn.opt_id_num; j++) {1083switch (prm->q.opt.bcn.opt_id[j]) {1084case bcn_req_ssid:1085/* SSID */1086#if (RM_MORE_DBG_MSG)1087RTW_INFO("RM: bcn_req_ssid\n");1088#endif1089pframe = rtw_set_ie(pframe, _SSID_IE_,1090pbss->Ssid.SsidLength,1091pbss->Ssid.Ssid, &my_len);1092break;1093case bcn_req_req:1094if (prm->q.opt.bcn.req_start == NULL)1095break;1096#if (RM_MORE_DBG_MSG)1097RTW_INFO("RM: bcn_req_req");1098#endif1099for (k=0; k<prm->q.opt.bcn.req_len; k++) {1100eid = prm->q.opt.bcn.req_start[k];11011102val8 = pbss->IELength - _FIXED_IE_LENGTH_;1103ptr = rtw_get_ie(pbss->IEs + _FIXED_IE_LENGTH_,1104eid, &len, val8);11051106if (!ptr)1107continue;1108#if (RM_MORE_DBG_MSG)1109switch (eid) {1110case EID_QBSSLoad:1111RTW_INFO("RM: EID_QBSSLoad\n");1112break;1113case EID_HTCapability:1114RTW_INFO("RM: EID_HTCapability\n");1115break;1116case _MDIE_:1117RTW_INFO("RM: EID_MobilityDomain\n");1118break;1119default:1120RTW_INFO("RM: EID %d todo\n",eid);1121break;1122}1123#endif1124pframe = rtw_set_ie(pframe, eid,1125len,ptr+2, &my_len);1126} /* for() */1127break;1128case bcn_req_ac_ch_rep:1129default:1130RTW_INFO("RM: OPT %d TODO\n",prm->q.opt.bcn.opt_id[j]);1131break;1132}1133}1134done:1135/*1136* update my length1137* content length does NOT include ID and LEN1138*/1139val8 = my_len - 2;1140rtw_set_fixed_ie(plen, 1, &val8, &j);11411142/* update length to caller */1143*fr_len += my_len;11441145return pframe;1146}11471148u8 rm_bcn_req_cond_mach(struct rm_obj *prm, struct wlan_network *pnetwork)1149{1150u8 val8;115111521153switch(prm->q.opt.bcn.rep_cond.cond) {1154case bcn_rep_cond_immediately:1155return _SUCCESS;1156case bcn_req_cond_rcpi_greater:1157val8 = rm_get_bcn_rcpi(prm, pnetwork);1158if (val8 > prm->q.opt.bcn.rep_cond.threshold)1159return _SUCCESS;1160break;1161case bcn_req_cond_rcpi_less:1162val8 = rm_get_bcn_rcpi(prm, pnetwork);1163if (val8 < prm->q.opt.bcn.rep_cond.threshold)1164return _SUCCESS;1165break;1166case bcn_req_cond_rsni_greater:1167val8 = rm_get_bcn_rsni(prm, pnetwork);1168if (val8 != 255 && val8 > prm->q.opt.bcn.rep_cond.threshold)1169return _SUCCESS;1170break;1171case bcn_req_cond_rsni_less:1172val8 = rm_get_bcn_rsni(prm, pnetwork);1173if (val8 != 255 && val8 < prm->q.opt.bcn.rep_cond.threshold)1174return _SUCCESS;1175break;1176default:1177RTW_ERR("RM: bcn_req cond %u not support\n",1178prm->q.opt.bcn.rep_cond.cond);1179break;1180}1181return _FALSE;1182}11831184static u8 *rm_gen_bcn_rep_ie (struct rm_obj *prm,1185u8 *pframe, struct wlan_network *pnetwork, unsigned int *fr_len)1186{1187int snr, i;1188u8 val8, *plen;1189u16 val16;1190u32 val32;1191u64 val64;1192unsigned int my_len;1193_adapter *padapter = prm->psta->padapter;119411951196my_len = 0;1197plen = pframe + 1;1198pframe = rtw_set_fixed_ie(pframe, 7, &prm->p.e_id, &my_len);11991200/* Actual Measurement StartTime */1201val64 = cpu_to_le64(prm->meas_start_time);1202pframe = rtw_set_fixed_ie(pframe, 8, (u8 *)&val64, &my_len);12031204/* Measurement Duration */1205val16 = prm->meas_end_time - prm->meas_start_time;1206val16 = cpu_to_le16(val16);1207pframe = rtw_set_fixed_ie(pframe, 2, (u8*)&val16, &my_len);12081209/* TODO1210* ReportedFrameInformation:1211* 0 :beacon or probe rsp1212* 1 :pilot frame1213*/1214val8 = 0; /* report frame info */1215pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);12161217/* RCPI */1218val8 = rm_get_bcn_rcpi(prm, pnetwork);1219pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);12201221/* RSNI */1222val8 = rm_get_bcn_rsni(prm, pnetwork);1223pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);12241225/* BSSID */1226pframe = rtw_set_fixed_ie(pframe, 6,1227(u8 *)&pnetwork->network.MacAddress, &my_len);12281229/*1230* AntennaID1231* 0: unknown1232* 255: multiple antenna (Diversity)1233*/1234val8 = 0;1235pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);12361237/* ParentTSF */1238val32 = prm->meas_start_time + pnetwork->network.PhyInfo.free_cnt;1239pframe = rtw_set_fixed_ie(pframe, 4, (u8 *)&val32, &my_len);12401241/* Generate Beacon detail */1242pframe = rm_gen_bcn_detail_elem(padapter, pframe,1243prm, pnetwork, &my_len);1244/*1245* update my length1246* content length does NOT include ID and LEN1247*/1248val8 = my_len - 2;1249rtw_set_fixed_ie(plen, 1, &val8, &i);12501251/* update length to caller */1252*fr_len += my_len;12531254return pframe;1255}12561257static int retrieve_scan_result(struct rm_obj *prm)1258{1259_irqL irqL;1260_list *plist, *phead;1261_queue *queue;1262_adapter *padapter = prm->psta->padapter;1263struct rtw_ieee80211_channel *pch_set;1264struct wlan_network *pnetwork = NULL;1265struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1266int i, meas_ch_num=0;1267PWLAN_BSSID_EX pbss;1268unsigned int matched_network;1269int len, my_len;1270u8 buf_idx, *pbuf = NULL, *tmp_buf = NULL;127112721273tmp_buf = rtw_malloc(MAX_XMIT_EXTBUF_SZ);1274if (tmp_buf == NULL)1275return 0;12761277my_len = 0;1278buf_idx = 0;1279matched_network = 0;1280queue = &(pmlmepriv->scanned_queue);12811282_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);12831284phead = get_list_head(queue);1285plist = get_next(phead);12861287/* get requested measurement channel set */1288pch_set = prm->q.ch_set;1289meas_ch_num = prm->q.ch_set_ch_amount;12901291/* search scan queue to find requested SSID */1292while (1) {12931294if (rtw_end_of_queue_search(phead, plist) == _TRUE)1295break;12961297pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);1298pbss = &pnetwork->network;12991300/*1301* report network if requested channel set contains1302* the channel matchs selected network1303*/1304if (rtw_chset_search_ch(adapter_to_chset(padapter),1305pbss->Configuration.DSConfig) == 0)1306goto next;13071308if (rtw_mlme_band_check(padapter, pbss->Configuration.DSConfig)1309== _FALSE)1310goto next;13111312if (rtw_validate_ssid(&(pbss->Ssid)) == _FALSE)1313goto next;13141315/* go through measurement requested channels */1316for (i = 0; i < meas_ch_num; i++) {13171318/* match channel */1319if (pch_set[i].hw_value != pbss->Configuration.DSConfig)1320continue;13211322/* match bssid */1323if (is_wildcard_bssid(prm->q.bssid) == FALSE)1324if (_rtw_memcmp(prm->q.bssid,1325pbss->MacAddress, 6) == _FALSE) {1326continue;1327}1328/*1329* default wildcard SSID. wildcard SSID:1330* A SSID value (null) used to represent all SSIDs1331*/13321333/* match ssid */1334if ((prm->q.opt.bcn.ssid.SsidLength > 0) &&1335_rtw_memcmp(prm->q.opt.bcn.ssid.Ssid,1336pbss->Ssid.Ssid,1337prm->q.opt.bcn.ssid.SsidLength) == _FALSE)1338continue;13391340/* match condition */1341if (rm_bcn_req_cond_mach(prm, pnetwork) == _FALSE) {1342RTW_INFO("RM: condition mismatch ch %u ssid %s bssid "MAC_FMT"\n",1343pch_set[i].hw_value, pbss->Ssid.Ssid,1344MAC_ARG(pbss->MacAddress));1345RTW_INFO("RM: condition %u:%u\n",1346prm->q.opt.bcn.rep_cond.cond,1347prm->q.opt.bcn.rep_cond.threshold);1348continue;1349}13501351/* Found a matched SSID */1352matched_network++;13531354RTW_INFO("RM: ch %u Found %s bssid "MAC_FMT"\n",1355pch_set[i].hw_value, pbss->Ssid.Ssid,1356MAC_ARG(pbss->MacAddress));13571358len = 0;1359_rtw_memset(tmp_buf, 0, MAX_XMIT_EXTBUF_SZ);1360rm_gen_bcn_rep_ie(prm, tmp_buf, pnetwork, &len);1361new_packet:1362if (my_len == 0) {1363pbuf = rtw_malloc(MAX_XMIT_EXTBUF_SZ);1364if (pbuf == NULL)1365goto fail;1366prm->buf[buf_idx].pbuf = pbuf;1367}13681369if ((MAX_XMIT_EXTBUF_SZ - (my_len+len+24+4)) > 0) {1370pbuf = rtw_set_fixed_ie(pbuf,1371len, tmp_buf, &my_len);1372prm->buf[buf_idx].len = my_len;1373} else {1374if (my_len == 0) /* not enough space */1375goto fail;13761377my_len = 0;1378buf_idx++;1379goto new_packet;1380}1381} /* for() */1382next:1383plist = get_next(plist);1384} /* while() */1385fail:1386_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);13871388if (tmp_buf)1389rtw_mfree(tmp_buf, MAX_XMIT_EXTBUF_SZ);13901391RTW_INFO("RM: Found %d matched %s\n", matched_network,1392prm->q.opt.bcn.ssid.Ssid);13931394if (prm->buf[buf_idx].pbuf)1395return buf_idx+1;13961397return 0;1398}13991400int issue_beacon_rep(struct rm_obj *prm)1401{1402int i, my_len;1403u8 *pframe;1404_adapter *padapter = prm->psta->padapter;1405struct pkt_attrib *pattr;1406struct xmit_frame *pmgntframe;1407struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1408int pkt_num;140914101411pkt_num = retrieve_scan_result(prm);14121413if (pkt_num == 0) {1414issue_null_reply(prm);1415return _SUCCESS;1416}14171418for (i=0;i<pkt_num;i++) {14191420pmgntframe = alloc_mgtxmitframe(pxmitpriv);1421if (pmgntframe == NULL) {1422RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);1423goto fail;1424}1425pattr = &pmgntframe->attrib;1426pframe = build_wlan_hdr(padapter,1427pmgntframe, prm->psta, WIFI_ACTION);1428pframe = rtw_set_fixed_ie(pframe,14293, &prm->p.category, &pattr->pktlen);14301431my_len = 0;1432pframe = rtw_set_fixed_ie(pframe,1433prm->buf[i].len, prm->buf[i].pbuf, &my_len);14341435pattr->pktlen += my_len;1436pattr->last_txcmdsz = pattr->pktlen;1437dump_mgntframe(padapter, pmgntframe);1438}1439fail:1440for (i=0;i<pkt_num;i++) {1441if (prm->buf[i].pbuf) {1442rtw_mfree(prm->buf[i].pbuf, MAX_XMIT_EXTBUF_SZ);1443prm->buf[i].pbuf = NULL;1444prm->buf[i].len = 0;1445}1446}1447return _SUCCESS;1448}14491450/* neighbor request */1451int issue_nb_req(struct rm_obj *prm)1452{1453_adapter *padapter = prm->psta->padapter;1454struct sta_info *psta = prm->psta;1455struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1456struct xmit_priv *pxmitpriv = &padapter->xmitpriv;1457struct xmit_frame *pmgntframe = NULL;1458struct pkt_attrib *pattr = NULL;1459u8 val8;1460u8 *pframe = NULL;146114621463RTW_INFO("RM: %s\n", __func__);14641465pmgntframe = alloc_mgtxmitframe(pxmitpriv);1466if (pmgntframe == NULL) {1467RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);1468return _FALSE;1469}1470pattr = &pmgntframe->attrib;1471pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);1472pframe = rtw_set_fixed_ie(pframe,14733, &prm->q.category, &pattr->pktlen);14741475if (prm->q.pssid) {14761477u8 sub_ie[64] = {0};1478u8 *pie = &sub_ie[2];14791480RTW_INFO("RM: Send NB Req to "MAC_FMT" for(SSID) %s searching\n",1481MAC_ARG(pmlmepriv->cur_network.network.MacAddress),1482pmlmepriv->cur_network.network.Ssid.Ssid);14831484val8 = strlen(prm->q.pssid);1485sub_ie[0] = 0; /*SSID*/1486sub_ie[1] = val8;14871488_rtw_memcpy(pie, prm->q.pssid, val8);14891490pframe = rtw_set_fixed_ie(pframe, val8 + 2,1491sub_ie, &pattr->pktlen);1492} else {14931494if (!pmlmepriv->cur_network.network.Ssid.SsidLength)1495RTW_INFO("RM: Send NB Req to "MAC_FMT"\n",1496MAC_ARG(pmlmepriv->cur_network.network.MacAddress));1497else {1498u8 sub_ie[64] = {0};1499u8 *pie = &sub_ie[2];15001501RTW_INFO("RM: Send NB Req to "MAC_FMT" for(SSID) %s searching\n",1502MAC_ARG(pmlmepriv->cur_network.network.MacAddress),1503pmlmepriv->cur_network.network.Ssid.Ssid);15041505sub_ie[0] = 0; /*SSID*/1506sub_ie[1] = pmlmepriv->cur_network.network.Ssid.SsidLength;15071508_rtw_memcpy(pie, pmlmepriv->cur_network.network.Ssid.Ssid,1509pmlmepriv->cur_network.network.Ssid.SsidLength);15101511pframe = rtw_set_fixed_ie(pframe,1512pmlmepriv->cur_network.network.Ssid.SsidLength + 2,1513sub_ie, &pattr->pktlen);1514}1515}15161517pattr->last_txcmdsz = pattr->pktlen;1518dump_mgntframe(padapter, pmgntframe);15191520return _SUCCESS;1521}15221523/* issue link measurement request */1524int issue_link_meas_req(struct rm_obj *prm)1525{1526_adapter *padapter = prm->psta->padapter;1527struct sta_info *psta = prm->psta;1528struct xmit_priv *pxmitpriv = &padapter->xmitpriv;1529struct xmit_frame *pmgntframe = NULL;1530struct pkt_attrib *pattr = NULL;1531u8 *pframe = NULL;1532s8 pwr_used, path_a_pwr;153315341535RTW_INFO("RM: %s\n", __func__);15361537pmgntframe = alloc_mgtxmitframe(pxmitpriv);1538if (pmgntframe == NULL) {1539RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);1540return _FALSE;1541}1542pattr = &pmgntframe->attrib;1543pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);15441545/* Category, Action code, Dialog token */1546pframe = rtw_set_fixed_ie(pframe,15473, &prm->q.category, &pattr->pktlen);15481549/* xmit power used */1550/* we don't know actual TX power due to RA may change TX rate;1551* But if we fix TX rate then we can get specific tx power1552*/1553pattr->rate = MGN_6M;1554rm_get_tx_power(padapter, RF_PATH_A, MGN_6M, &pwr_used);1555pframe = rtw_set_fixed_ie(pframe,15561, &pwr_used, &pattr->pktlen);15571558/* Max xmit power */1559rm_get_path_a_max_tx_power(padapter, &path_a_pwr);1560pframe = rtw_set_fixed_ie(pframe,15611, &path_a_pwr, &pattr->pktlen);15621563pattr->last_txcmdsz = pattr->pktlen;1564dump_mgntframe(padapter, pmgntframe);15651566return _SUCCESS;1567}15681569/* issue link measurement report */1570int issue_link_meas_rep(struct rm_obj *prm)1571{1572u8 val8;1573u8 *pframe;1574unsigned int my_len;1575_adapter *padapter = prm->psta->padapter;1576struct xmit_frame *pmgntframe;1577struct pkt_attrib *pattr;1578struct xmit_priv *pxmitpriv = &padapter->xmitpriv;1579struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1580struct sta_info *psta = prm->psta;1581int i;1582u8 tpc[4];1583s8 pwr_used;158415851586RTW_INFO("RM: %s\n", __func__);15871588pmgntframe = alloc_mgtxmitframe(pxmitpriv);1589if (pmgntframe == NULL) {1590RTW_ERR("RM: ERR %s alloc xmit_frame fail\n",__func__);1591return _FALSE;1592}1593pattr = &pmgntframe->attrib;1594pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);1595/* Category, action code, Dialog token */1596pframe = rtw_set_fixed_ie(pframe, 3,1597&prm->p.category, &pattr->pktlen);15981599my_len = 0;16001601/* TPC report */1602rm_get_tx_power(padapter, RF_PATH_A, MGN_6M, &pwr_used);1603tpc[0] = EID_TPC;1604tpc[1] = 2; /* length */16051606/* TX power */1607tpc[2] = pwr_used;16081609/* link margin */1610rm_get_rx_sensitivity(padapter, prm->q.rx_bw, prm->q.rx_rate, &pwr_used);1611tpc[3] = prm->q.rx_pwr - pwr_used; /* RX sensitivity */1612pattr->rate = MGN_6M; /* use fix rate to get fixed RX sensitivity */16131614#if (RM_MORE_DBG_MSG)1615RTW_INFO("RM: rx_pwr=%ddBm - rx_sensitivity=%ddBm = link_margin=%ddB\n",1616prm->q.rx_pwr, pwr_used, tpc[3]);1617#endif1618pframe = rtw_set_fixed_ie(pframe, 4, tpc, &my_len);16191620/* RECV antenna ID */1621val8 = 0; /* unknown antenna */1622pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16231624/* XMIT antenna ID */1625/* Fix rate 6M(1T) always use main antenna to TX */1626val8 = 1; /* main antenna */1627pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16281629/* RCPI */1630val8 = translate_dbm_to_rcpi(prm->q.rx_pwr);1631pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16321633/* RSNI */1634val8 = prm->q.rx_rsni;1635pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16361637/* length */1638//val8 = (u8)my_len-2;1639//rtw_set_fixed_ie(plen, 1, &val8, &i); /* use variable i to ignore it */16401641pattr->pktlen += my_len;1642pattr->last_txcmdsz = pattr->pktlen;1643dump_mgntframe(padapter, pmgntframe);16441645return _SUCCESS;1646}16471648static u8 *rm_gen_bcn_req_s_elem(_adapter *padapter,1649u8 *pframe, unsigned int *fr_len)1650{1651u8 val8;1652unsigned int my_len = 0;1653u8 bssid[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};165416551656val8 = bcn_req_active; /* measurement mode T8-64 */1657pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16581659pframe = rtw_set_fixed_ie(pframe, 6, bssid, &my_len);16601661/* update length to caller */1662*fr_len += my_len;16631664/* optional subelements */1665return pframe;1666}16671668static u8 *rm_gen_ch_load_req_s_elem(_adapter *padapter,1669u8 *pframe, unsigned int *fr_len)1670{1671u8 val8;1672unsigned int my_len = 0;167316741675val8 = 1; /* 1: channel load T8-60 */1676pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16771678val8 = 2; /* channel load length = 2 (extensible) */1679pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16801681val8 = 0; /* channel load condition : 0 (issue when meas done) T8-61 */1682pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16831684val8 = 0; /* channel load reference value : 0 */1685pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);16861687/* update length to caller */1688*fr_len += my_len;16891690return pframe;1691}16921693static u8 *rm_gen_noise_histo_req_s_elem(_adapter *padapter,1694u8 *pframe, unsigned int *fr_len)1695{1696u8 val8;1697unsigned int my_len = 0;169816991700val8 = 1; /* 1: noise histogram T8-62 */1701pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);17021703val8 = 2; /* noise histogram length = 2 (extensible) */1704pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);17051706val8 = 0; /* noise histogram condition : 0 (issue when meas done) T8-63 */1707pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);17081709val8 = 0; /* noise histogram reference value : 0 */1710pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);17111712/* update length to caller */1713*fr_len += my_len;17141715return pframe;1716}17171718int issue_radio_meas_req(struct rm_obj *prm)1719{1720u8 val8;1721u8 *pframe;1722u8 *plen;1723u16 val16;1724int my_len, i;1725struct xmit_frame *pmgntframe;1726struct pkt_attrib *pattr;1727_adapter *padapter = prm->psta->padapter;1728struct xmit_priv *pxmitpriv = &padapter->xmitpriv;172917301731RTW_INFO("RM: %s - %s\n", __func__, rm_type_req_name(prm->q.m_type));17321733pmgntframe = alloc_mgtxmitframe(pxmitpriv);1734if (pmgntframe == NULL) {1735RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);1736return _FALSE;1737}1738pattr = &pmgntframe->attrib;1739pframe = build_wlan_hdr(padapter, pmgntframe, prm->psta, WIFI_ACTION);1740pframe = rtw_set_fixed_ie(pframe, 3, &prm->q.category, &pattr->pktlen);17411742/* repeat */1743val16 = cpu_to_le16(prm->q.rpt);1744pframe = rtw_set_fixed_ie(pframe, 2,1745(unsigned char *)&(val16), &pattr->pktlen);17461747my_len = 0;1748plen = pframe + 1;1749pframe = rtw_set_fixed_ie(pframe, 7, &prm->q.e_id, &my_len);17501751/* random interval */1752val16 = 100; /* 100 TU */1753val16 = cpu_to_le16(val16);1754pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);17551756/* measurement duration */1757val16 = 100;1758val16 = cpu_to_le16(val16);1759pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);17601761/* optional subelement */1762switch (prm->q.m_type) {1763case bcn_req:1764pframe = rm_gen_bcn_req_s_elem(padapter, pframe, &my_len);1765break;1766case ch_load_req:1767pframe = rm_gen_ch_load_req_s_elem(padapter, pframe, &my_len);1768break;1769case noise_histo_req:1770pframe = rm_gen_noise_histo_req_s_elem(padapter,1771pframe, &my_len);1772break;1773case basic_req:1774default:1775break;1776}17771778/* length */1779val8 = (u8)my_len - 2;1780rtw_set_fixed_ie(plen, 1, &val8, &i);17811782pattr->pktlen += my_len;17831784pattr->last_txcmdsz = pattr->pktlen;1785dump_mgntframe(padapter, pmgntframe);17861787return _SUCCESS;1788}17891790int rm_radio_meas_report_cond(struct rm_obj *prm)1791{1792u8 val8;1793int i;179417951796switch (prm->q.m_type) {1797case ch_load_req:17981799val8 = prm->p.ch_load;1800switch (prm->q.opt.clm.rep_cond.cond) {1801case ch_load_cond_immediately:1802return _SUCCESS;1803case ch_load_cond_anpi_equal_greater:1804if (val8 >= prm->q.opt.clm.rep_cond.threshold)1805return _SUCCESS;1806case ch_load_cond_anpi_equal_less:1807if (val8 <= prm->q.opt.clm.rep_cond.threshold)1808return _SUCCESS;1809default:1810break;1811}1812break;1813case noise_histo_req:1814val8 = prm->p.anpi;1815switch (prm->q.opt.nhm.rep_cond.cond) {1816case noise_histo_cond_immediately:1817return _SUCCESS;1818case noise_histo_cond_anpi_equal_greater:1819if (val8 >= prm->q.opt.nhm.rep_cond.threshold)1820return _SUCCESS;1821break;1822case noise_histo_cond_anpi_equal_less:1823if (val8 <= prm->q.opt.nhm.rep_cond.threshold)1824return _SUCCESS;1825break;1826default:1827break;1828}1829break;1830default:1831break;1832}1833return _FAIL;1834}18351836int retrieve_radio_meas_result(struct rm_obj *prm)1837{1838HAL_DATA_TYPE *hal_data = GET_HAL_DATA(prm->psta->padapter);1839int i, ch = -1;1840u8 val8;184118421843ch = rtw_chset_search_ch(adapter_to_chset(prm->psta->padapter),1844prm->q.ch_num);18451846if ((ch == -1) || (ch >= MAX_CHANNEL_NUM)) {1847RTW_ERR("RM: get ch(CH:%d) fail\n", prm->q.ch_num);1848ch = 0;1849}18501851switch (prm->q.m_type) {1852case ch_load_req:1853#ifdef CONFIG_RTW_ACS1854val8 = hal_data->acs.clm_ratio[ch];1855#else1856val8 = 0;1857#endif1858prm->p.ch_load = val8;1859break;1860case noise_histo_req:1861#ifdef CONFIG_RTW_ACS1862/* ANPI */1863prm->p.anpi = hal_data->acs.nhm_ratio[ch];18641865/* IPI 0~10 */1866for (i=0;i<11;i++)1867prm->p.ipi[i] = hal_data->acs.nhm[ch][i];18681869#else1870val8 = 0;1871prm->p.anpi = val8;1872for (i=0;i<11;i++)1873prm->p.ipi[i] = val8;1874#endif1875break;1876default:1877break;1878}1879return _SUCCESS;1880}18811882int issue_radio_meas_rep(struct rm_obj *prm)1883{1884u8 val8;1885u8 *pframe;1886u8 *plen;1887u16 val16;1888u64 val64;1889unsigned int my_len;1890_adapter *padapter = prm->psta->padapter;1891struct xmit_frame *pmgntframe;1892struct pkt_attrib *pattr;1893struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1894struct sta_info *psta = prm->psta;1895int i;189618971898RTW_INFO("RM: %s\n", __func__);18991900pmgntframe = alloc_mgtxmitframe(pxmitpriv);1901if (pmgntframe == NULL) {1902RTW_ERR("RM: ERR %s alloc xmit_frame fail\n",__func__);1903return _FALSE;1904}1905pattr = &pmgntframe->attrib;1906pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);1907pframe = rtw_set_fixed_ie(pframe, 3,1908&prm->p.category, &pattr->pktlen);19091910my_len = 0;1911plen = pframe + 1;1912pframe = rtw_set_fixed_ie(pframe, 7, &prm->p.e_id, &my_len);19131914/* Actual Meas start time - 8 bytes */1915val64 = cpu_to_le64(prm->meas_start_time);1916pframe = rtw_set_fixed_ie(pframe, 8, (u8 *)&val64, &my_len);19171918/* measurement duration */1919val16 = prm->meas_end_time - prm->meas_start_time;1920val16 = cpu_to_le16(val16);1921pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);19221923/* optional subelement */1924switch (prm->q.m_type) {1925case ch_load_req:1926val8 = prm->p.ch_load;1927pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);1928break;1929case noise_histo_req:1930/*1931* AntennaID1932* 0: unknown1933* 255: multiple antenna (Diversity)1934*/1935val8 = 0;1936pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);1937/* ANPI */1938val8 = prm->p.anpi;1939pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);1940/* IPI 0~10 */1941for (i=0;i<11;i++) {1942val8 = prm->p.ipi[i];1943pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);1944}1945break;1946default:1947break;1948}1949/* length */1950val8 = (u8)my_len-2;1951rtw_set_fixed_ie(plen, 1, &val8, &i); /* use variable i to ignore it */19521953pattr->pktlen += my_len;1954pattr->last_txcmdsz = pattr->pktlen;1955dump_mgntframe(padapter, pmgntframe);19561957return _SUCCESS;1958}19591960void rtw_ap_parse_sta_rm_en_cap(_adapter *padapter,1961struct sta_info *psta, struct rtw_ieee802_11_elems *elem)1962{1963if (elem->rm_en_cap) {1964RTW_INFO("assoc.rm_en_cap="RM_CAP_FMT"\n",1965RM_CAP_ARG(elem->rm_en_cap));1966_rtw_memcpy(psta->rm_en_cap,1967(elem->rm_en_cap), elem->rm_en_cap_len);1968}1969}19701971void RM_IE_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)1972{1973int i;19741975_rtw_memcpy(&padapter->rmpriv.rm_en_cap_assoc, pIE->data, pIE->Length);1976RTW_INFO("assoc.rm_en_cap="RM_CAP_FMT"\n", RM_CAP_ARG(pIE->data));1977}19781979/* Debug command */19801981#if (RM_SUPPORT_IWPRIV_DBG)1982static int hex2num(char c)1983{1984if (c >= '0' && c <= '9')1985return c - '0';1986if (c >= 'a' && c <= 'f')1987return c - 'a' + 10;1988if (c >= 'A' && c <= 'F')1989return c - 'A' + 10;1990return -1;1991}19921993int hex2byte(const char *hex)1994{1995int a, b;1996a = hex2num(*hex++);1997if (a < 0)1998return -1;1999b = hex2num(*hex++);2000if (b < 0)2001return -1;2002return (a << 4) | b;2003}20042005static char * hwaddr_parse(char *txt, u8 *addr)2006{2007size_t i;20082009for (i = 0; i < ETH_ALEN; i++) {2010int a;20112012a = hex2byte(txt);2013if (a < 0)2014return NULL;2015txt += 2;2016addr[i] = a;2017if (i < ETH_ALEN - 1 && *txt++ != ':')2018return NULL;2019}2020return txt;2021}20222023void rm_dbg_list_sta(_adapter *padapter, char *s)2024{2025int i;2026_irqL irqL;2027struct sta_info *psta;2028struct sta_priv *pstapriv = &padapter->stapriv;2029_list *plist, *phead;203020312032sprintf(pstr(s), "\n");2033_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);2034for (i = 0; i < NUM_STA; i++) {2035phead = &(pstapriv->sta_hash[i]);2036plist = get_next(phead);20372038while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {2039psta = LIST_CONTAINOR(plist,2040struct sta_info, hash_list);20412042plist = get_next(plist);20432044sprintf(pstr(s), "=========================================\n");2045sprintf(pstr(s), "mac=" MAC_FMT "\n",2046MAC_ARG(psta->cmn.mac_addr));2047sprintf(pstr(s), "state=0x%x, aid=%d, macid=%d\n",2048psta->state, psta->cmn.aid, psta->cmn.mac_id);2049sprintf(pstr(s), "rm_cap="RM_CAP_FMT"\n",2050RM_CAP_ARG(psta->rm_en_cap));2051}20522053}2054_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);2055sprintf(pstr(s), "=========================================\n");2056}20572058void rm_dbg_help(_adapter *padapter, char *s)2059{2060int i;206120622063sprintf(pstr(s), "\n");2064sprintf(pstr(s), "rrm list_sta\n");2065sprintf(pstr(s), "rrm list_meas\n");20662067sprintf(pstr(s), "rrm add_meas <aid=1|mac=>,m=<bcn|clm|nhm|nb|link>,rpt=\n");2068sprintf(pstr(s), "rrm run_meas <aid=1|evid=>\n");2069sprintf(pstr(s), "rrm del_meas\n");20702071sprintf(pstr(s), "rrm run_meas rmid=xxxx,ev=xx\n");2072sprintf(pstr(s), "rrm activate\n");20732074for (i=0;i<RM_EV_max;i++)2075sprintf(pstr(s), "\t%2d %s\n",i, rm_event_name(i) );2076sprintf(pstr(s), "\n");2077}20782079struct sta_info *rm_get_sta(_adapter *padapter, u16 aid, u8* pbssid)2080{2081int i;2082_irqL irqL;2083struct sta_info *psta = NULL;2084struct sta_priv *pstapriv = &padapter->stapriv;2085_list *plist, *phead;208620872088_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);20892090for (i = 0; i < NUM_STA; i++) {2091phead = &(pstapriv->sta_hash[i]);2092plist = get_next(phead);20932094while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {2095psta = LIST_CONTAINOR(plist,2096struct sta_info, hash_list);20972098plist = get_next(plist);20992100if (psta->cmn.aid == aid)2101goto done;21022103if (pbssid && _rtw_memcmp(psta->cmn.mac_addr,2104pbssid, 6))2105goto done;2106}21072108}2109psta = NULL;2110done:2111_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);2112return psta;2113}21142115static int rm_dbg_modify_meas(_adapter *padapter, char *s)2116{2117struct rm_priv *prmpriv = &padapter->rmpriv;2118struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;2119struct rm_obj *prm;2120struct sta_info *psta;2121char *pmac, *ptr, *paid, *prpt, *pnbp, *pclm, *pnhm, *pbcn, *plnk;2122unsigned val;2123u8 bssid[ETH_ALEN];212421252126/* example :2127* rrm add_meas <aid=1|mac=>,m=<nb|clm|nhm|bcn|link>,<rept=>2128* rrm run_meas <aid=1|evid=>2129*/2130paid = strstr(s, "aid=");2131pmac = strstr(s, "mac=");2132pbcn = strstr(s, "m=bcn");2133pclm = strstr(s, "m=clm");2134pnhm = strstr(s, "m=nhm");2135pnbp = strstr(s, "m=nb");2136plnk = strstr(s, "m=link");2137prpt = strstr(s, "rpt=");21382139/* set all ',' to NULL (end of line) */2140ptr = s;2141while (ptr) {2142ptr = strchr(ptr, ',');2143if (ptr) {2144*(ptr) = 0x0;2145ptr++;2146}2147}2148prm = (struct rm_obj *)prmpriv->prm_sel;2149prm->q.m_token = 1;2150psta = prm->psta;21512152if (paid) { /* find sta_info according to aid */2153paid += 4; /* skip aid= */2154sscanf(paid, "%u", &val); /* aid=x */2155psta = rm_get_sta(padapter, val, NULL);21562157} else if (pmac) { /* find sta_info according to bssid */2158pmac += 4; /* skip mac= */2159if (hwaddr_parse(pmac, bssid) == NULL) {2160sprintf(pstr(s), "Err: \nincorrect mac format\n");2161return _FAIL;2162}2163psta = rm_get_sta(padapter, 0xff, bssid);2164}21652166if (psta) {2167prm->psta = psta;21682169#if 02170prm->q.diag_token = psta->rm_diag_token++;2171#else2172/* TODO dialog should base on sta_info */2173do {2174pmlmeinfo->dialogToken++;2175} while (pmlmeinfo->dialogToken == 0);21762177prm->q.diag_token = pmlmeinfo->dialogToken;2178#endif2179prm->rmid = psta->cmn.aid << 162180| prm->q.diag_token << 82181| RM_MASTER;2182} else2183return _FAIL;21842185prm->q.action_code = RM_ACT_RADIO_MEAS_REQ;2186if (pbcn) {2187prm->q.m_type = bcn_req;2188} else if (pnhm) {2189prm->q.m_type = noise_histo_req;2190} else if (pclm) {2191prm->q.m_type = ch_load_req;2192} else if (pnbp) {2193prm->q.action_code = RM_ACT_NB_REP_REQ;2194} else if (plnk) {2195prm->q.action_code = RM_ACT_LINK_MEAS_REQ;2196} else2197return _FAIL;21982199if (prpt) {2200prpt += 4; /* skip rpt= */2201sscanf(prpt, "%u", &val);2202prm->q.rpt = (u8)val;2203}22042205return _SUCCESS;2206}22072208static void rm_dbg_activate_meas(_adapter *padapter, char *s)2209{2210struct rm_priv *prmpriv = &(padapter->rmpriv);2211struct rm_obj *prm;221222132214if (prmpriv->prm_sel == NULL) {2215sprintf(pstr(s), "\nErr: No inActivate measurement\n");2216return;2217}2218prm = (struct rm_obj *)prmpriv->prm_sel;22192220/* verify attributes */2221if (prm->psta == NULL) {2222sprintf(pstr(s), "\nErr: inActivate meas has no psta\n");2223return;2224}22252226/* measure current channel */2227prm->q.ch_num = padapter->mlmeextpriv.cur_channel;2228prm->q.op_class = rm_get_oper_class_via_ch(prm->q.ch_num);22292230/* enquee rmobj */2231rm_enqueue_rmobj(padapter, prm, _FALSE);22322233sprintf(pstr(s), "\nActivate rmid=%x, state=%s, meas_type=%s\n",2234prm->rmid, rm_state_name(prm->state),2235rm_type_req_name(prm->q.m_type));22362237sprintf(pstr(s), "aid=%d, mac=" MAC_FMT "\n",2238prm->psta->cmn.aid, MAC_ARG(prm->psta->cmn.mac_addr));22392240/* clearn inActivate prm info */2241prmpriv->prm_sel = NULL;2242}22432244static void rm_dbg_add_meas(_adapter *padapter, char *s)2245{2246struct rm_priv *prmpriv = &(padapter->rmpriv);2247struct rm_obj *prm;2248char *pact;224922502251/* example :2252* rrm add_meas <aid=1|mac=>,m=<nb|clm|nhm|link>2253* rrm run_meas <aid=1|evid=>2254*/2255prm = (struct rm_obj *)prmpriv->prm_sel;2256if (prm == NULL)2257prm = rm_alloc_rmobj(padapter);22582259if (prm == NULL) {2260sprintf(pstr(s), "\nErr: alloc meas fail\n");2261return;2262}22632264prmpriv->prm_sel = prm;22652266pact = strstr(s, "act");2267if (rm_dbg_modify_meas(padapter, s) == _FAIL) {22682269sprintf(pstr(s), "\nErr: add meas fail\n");2270rm_free_rmobj(prm);2271prmpriv->prm_sel = NULL;2272return;2273}2274prm->q.category = RTW_WLAN_CATEGORY_RADIO_MEAS;2275prm->q.e_id = _MEAS_REQ_IE_; /* 38 */22762277sprintf(pstr(s), "\nAdd rmid=%x, meas_type=%s ok\n",2278prm->rmid, rm_type_req_name(prm->q.m_type));22792280if (prm->psta)2281sprintf(pstr(s), "mac="MAC_FMT"\n",2282MAC_ARG(prm->psta->cmn.mac_addr));22832284if (pact)2285rm_dbg_activate_meas(padapter, pstr(s));2286}22872288static void rm_dbg_del_meas(_adapter *padapter, char *s)2289{2290struct rm_priv *prmpriv = &padapter->rmpriv;2291struct rm_obj *prm = (struct rm_obj *)prmpriv->prm_sel;229222932294if (prm) {2295sprintf(pstr(s), "\ndelete rmid=%x\n",prm->rmid);22962297/* free inActivate meas - enqueue yet */2298prmpriv->prm_sel = NULL;2299rtw_mfree(prmpriv->prm_sel, sizeof(struct rm_obj));2300} else2301sprintf(pstr(s), "Err: no inActivate measurement\n");2302}23032304static void rm_dbg_run_meas(_adapter *padapter, char *s)2305{2306struct rm_obj *prm;2307char *pevid, *prmid;2308u32 rmid, evid;230923102311prmid = strstr(s, "rmid="); /* hex */2312pevid = strstr(s, "evid="); /* dec */23132314if (prmid && pevid) {2315prmid += 5; /* rmid= */2316sscanf(prmid, "%x", &rmid);23172318pevid += 5; /* evid= */2319sscanf(pevid, "%u", &evid);2320} else {2321sprintf(pstr(s), "\nErr: incorrect attribute\n");2322return;2323}23242325prm = rm_get_rmobj(padapter, rmid);23262327if (!prm) {2328sprintf(pstr(s), "\nErr: measurement not found\n");2329return;2330}23312332if (evid >= RM_EV_max) {2333sprintf(pstr(s), "\nErr: wrong event id\n");2334return;2335}23362337rm_post_event(padapter, prm->rmid, evid);2338sprintf(pstr(s), "\npost %s to rmid=%x\n",rm_event_name(evid), rmid);2339}23402341static void rm_dbg_show_meas(struct rm_obj *prm, char *s)2342{2343struct sta_info *psta;23442345psta = prm->psta;23462347if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {23482349sprintf(pstr(s), "\nrmid=%x, meas_type=%s\n",2350prm->rmid, rm_type_req_name(prm->q.m_type));23512352} else if (prm->q.action_code == RM_ACT_NB_REP_REQ) {23532354sprintf(pstr(s), "\nrmid=%x, action=neighbor_req\n",2355prm->rmid);2356} else2357sprintf(pstr(s), "\nrmid=%x, action=unknown\n",2358prm->rmid);23592360if (psta)2361sprintf(pstr(s), "aid=%d, mac="MAC_FMT"\n",2362psta->cmn.aid, MAC_ARG(psta->cmn.mac_addr));23632364sprintf(pstr(s), "clock=%d, state=%s, rpt=%u/%u\n",2365(int)ATOMIC_READ(&prm->pclock->counter),2366rm_state_name(prm->state), prm->p.rpt, prm->q.rpt);2367}23682369static void rm_dbg_list_meas(_adapter *padapter, char *s)2370{2371int meas_amount;2372_irqL irqL;2373struct rm_obj *prm;2374struct sta_info *psta;2375struct rm_priv *prmpriv = &padapter->rmpriv;2376_queue *queue = &prmpriv->rm_queue;2377_list *plist, *phead;237823792380sprintf(pstr(s), "\n");2381_enter_critical(&queue->lock, &irqL);2382phead = get_list_head(queue);2383plist = get_next(phead);2384meas_amount = 0;23852386while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {2387prm = LIST_CONTAINOR(plist, struct rm_obj, list);2388meas_amount++;2389plist = get_next(plist);2390psta = prm->psta;2391sprintf(pstr(s), "=========================================\n");23922393rm_dbg_show_meas(prm, s);2394}2395_exit_critical(&queue->lock, &irqL);23962397sprintf(pstr(s), "=========================================\n");23982399if (meas_amount==0) {2400sprintf(pstr(s), "No Activate measurement\n");2401sprintf(pstr(s), "=========================================\n");2402}24032404if (prmpriv->prm_sel == NULL)2405sprintf(pstr(s), "\nNo inActivate measurement\n");2406else {2407sprintf(pstr(s), "\ninActivate measurement\n");2408rm_dbg_show_meas((struct rm_obj *)prmpriv->prm_sel, s);2409}2410}2411#endif /* RM_SUPPORT_IWPRIV_DBG */24122413void rm_dbg_cmd(_adapter *padapter, char *s)2414{2415unsigned val;2416char *paid;2417struct sta_info *psta=NULL;24182419#if (RM_SUPPORT_IWPRIV_DBG)2420if (_rtw_memcmp(s, "help", 4)) {2421rm_dbg_help(padapter, s);24222423} else if (_rtw_memcmp(s, "list_sta", 8)) {2424rm_dbg_list_sta(padapter, s);24252426} else if (_rtw_memcmp(s, "list_meas", 9)) {2427rm_dbg_list_meas(padapter, s);24282429} else if (_rtw_memcmp(s, "add_meas", 8)) {2430rm_dbg_add_meas(padapter, s);24312432} else if (_rtw_memcmp(s, "del_meas", 8)) {2433rm_dbg_del_meas(padapter, s);24342435} else if (_rtw_memcmp(s, "activate", 8)) {2436rm_dbg_activate_meas(padapter, s);24372438} else if (_rtw_memcmp(s, "run_meas", 8)) {2439rm_dbg_run_meas(padapter, s);24402441} else if (_rtw_memcmp(s, "nb", 2)) {24422443paid = strstr(s, "aid=");24442445if (paid) { /* find sta_info according to aid */2446paid += 4; /* skip aid= */2447sscanf(paid, "%u", &val); /* aid=x */2448psta = rm_get_sta(padapter, val, NULL);24492450if (psta)2451rm_add_nb_req(padapter, psta);2452}2453}2454#else2455sprintf(pstr(s), "\n");2456sprintf(pstr(s), "rrm debug command was disabled\n");2457#endif2458}2459#endif /* CONFIG_RTW_80211K */246024612462