rtw_rm.c 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2017 Realtek Corporation.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. *****************************************************************************/
  15. #include <drv_types.h>
  16. #include <hal_data.h>
  17. #include "rtw_rm_fsm.h"
  18. #define pstr(s) s+strlen(s)
  19. u8 rm_post_event_hdl(_adapter *padapter, u8 *pbuf)
  20. {
  21. #ifdef CONFIG_RTW_80211K
  22. struct rm_event *pev = (struct rm_event *)pbuf;
  23. _rm_post_event(padapter, pev->rmid, pev->evid);
  24. rm_handler(padapter, pev);
  25. #endif
  26. return H2C_SUCCESS;
  27. }
  28. #ifdef CONFIG_RTW_80211K
  29. /* 802.11-2012 Table E-1 Operationg classes in United States */
  30. static RT_OPERATING_CLASS RTW_OP_CLASS_US[] = {
  31. /* 0, OP_CLASS_NULL */ { 0, 0, {}},
  32. /* 1, OP_CLASS_1 */ {115, 4, {36, 40, 44, 48}},
  33. /* 2, OP_CLASS_2 */ {118, 4, {52, 56, 60, 64}},
  34. /* 3, OP_CLASS_3 */ {124, 4, {149, 153, 157, 161}},
  35. /* 4, OP_CLASS_4 */ {121, 11, {100, 104, 108, 112, 116, 120, 124,
  36. 128, 132, 136, 140}},
  37. /* 5, OP_CLASS_5 */ {125, 5, {149, 153, 157, 161, 165}},
  38. /* 6, OP_CLASS_12 */ { 81, 11, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}
  39. };
  40. struct cmd_meas_type_ {
  41. u8 id;
  42. char *name;
  43. };
  44. char *rm_type_req_name(u8 meas_type) {
  45. switch (meas_type) {
  46. case basic_req:
  47. return "basic_req";
  48. case cca_req:
  49. return "cca_req";
  50. case rpi_histo_req:
  51. return "rpi_histo_req";
  52. case ch_load_req:
  53. return "ch_load_req";
  54. case noise_histo_req:
  55. return "noise_histo_req";
  56. case bcn_req:
  57. return "bcn_req";
  58. case frame_req:
  59. return "frame_req";
  60. case sta_statis_req:
  61. return "sta_statis_req";
  62. }
  63. return "unknown_req";
  64. };
  65. char *rm_type_rep_name(u8 meas_type) {
  66. switch (meas_type) {
  67. case basic_rep:
  68. return "basic_rep";
  69. case cca_rep:
  70. return "cca_rep";
  71. case rpi_histo_rep:
  72. return "rpi_histo_rep";
  73. case ch_load_rep:
  74. return "ch_load_rep";
  75. case noise_histo_rep:
  76. return "noise_histo_rep";
  77. case bcn_rep:
  78. return "bcn_rep";
  79. case frame_rep:
  80. return "frame_rep";
  81. case sta_statis_rep:
  82. return "sta_statis_rep";
  83. }
  84. return "unknown_rep";
  85. };
  86. char *rm_en_cap_name(enum rm_cap_en en)
  87. {
  88. switch (en) {
  89. case RM_LINK_MEAS_CAP_EN:
  90. return "RM_LINK_MEAS_CAP_EN";
  91. case RM_NB_REP_CAP_EN:
  92. return "RM_NB_REP_CAP_EN";
  93. case RM_PARAL_MEAS_CAP_EN:
  94. return "RM_PARAL_MEAS_CAP_EN";
  95. case RM_REPEAT_MEAS_CAP_EN:
  96. return "RM_REPEAT_MEAS_CAP_EN";
  97. case RM_BCN_PASSIVE_MEAS_CAP_EN:
  98. return "RM_BCN_PASSIVE_MEAS_CAP_EN";
  99. case RM_BCN_ACTIVE_MEAS_CAP_EN:
  100. return "RM_BCN_ACTIVE_MEAS_CAP_EN";
  101. case RM_BCN_TABLE_MEAS_CAP_EN:
  102. return "RM_BCN_TABLE_MEAS_CAP_EN";
  103. case RM_BCN_MEAS_REP_COND_CAP_EN:
  104. return "RM_BCN_MEAS_REP_COND_CAP_EN";
  105. case RM_FRAME_MEAS_CAP_EN:
  106. return "RM_FRAME_MEAS_CAP_EN";
  107. case RM_CH_LOAD_CAP_EN:
  108. return "RM_CH_LOAD_CAP_EN";
  109. case RM_NOISE_HISTO_CAP_EN:
  110. return "RM_NOISE_HISTO_CAP_EN";
  111. case RM_STATIS_MEAS_CAP_EN:
  112. return "RM_STATIS_MEAS_CAP_EN";
  113. case RM_LCI_MEAS_CAP_EN:
  114. return "RM_LCI_MEAS_CAP_EN";
  115. case RM_LCI_AMIMUTH_CAP_EN:
  116. return "RM_LCI_AMIMUTH_CAP_EN";
  117. case RM_TRANS_STREAM_CAT_MEAS_CAP_EN:
  118. return "RM_TRANS_STREAM_CAT_MEAS_CAP_EN";
  119. case RM_TRIG_TRANS_STREAM_CAT_MEAS_CAP_EN:
  120. return "RM_TRIG_TRANS_STREAM_CAT_MEAS_CAP_EN";
  121. case RM_AP_CH_REP_CAP_EN:
  122. return "RM_AP_CH_REP_CAP_EN";
  123. case RM_RM_MIB_CAP_EN:
  124. return "RM_RM_MIB_CAP_EN";
  125. case RM_OP_CH_MAX_MEAS_DUR0:
  126. return "RM_OP_CH_MAX_MEAS_DUR0";
  127. case RM_OP_CH_MAX_MEAS_DUR1:
  128. return "RM_OP_CH_MAX_MEAS_DUR1";
  129. case RM_OP_CH_MAX_MEAS_DUR2:
  130. return "RM_OP_CH_MAX_MEAS_DUR2";
  131. case RM_NONOP_CH_MAX_MEAS_DUR0:
  132. return "RM_NONOP_CH_MAX_MEAS_DUR0";
  133. case RM_NONOP_CH_MAX_MEAS_DUR1:
  134. return "RM_NONOP_CH_MAX_MEAS_DUR1";
  135. case RM_NONOP_CH_MAX_MEAS_DUR2:
  136. return "RM_NONOP_CH_MAX_MEAS_DUR2";
  137. case RM_MEAS_PILOT_CAP0:
  138. return "RM_MEAS_PILOT_CAP0"; /* 24-26 */
  139. case RM_MEAS_PILOT_CAP1:
  140. return "RM_MEAS_PILOT_CAP1";
  141. case RM_MEAS_PILOT_CAP2:
  142. return "RM_MEAS_PILOT_CAP2";
  143. case RM_MEAS_PILOT_TRANS_INFO_CAP_EN:
  144. return "RM_MEAS_PILOT_TRANS_INFO_CAP_EN";
  145. case RM_NB_REP_TSF_OFFSET_CAP_EN:
  146. return "RM_NB_REP_TSF_OFFSET_CAP_EN";
  147. case RM_RCPI_MEAS_CAP_EN:
  148. return "RM_RCPI_MEAS_CAP_EN"; /* 29 */
  149. case RM_RSNI_MEAS_CAP_EN:
  150. return "RM_RSNI_MEAS_CAP_EN";
  151. case RM_BSS_AVG_ACCESS_DELAY_CAP_EN:
  152. return "RM_BSS_AVG_ACCESS_DELAY_CAP_EN";
  153. case RM_AVALB_ADMIS_CAPACITY_CAP_EN:
  154. return "RM_AVALB_ADMIS_CAPACITY_CAP_EN";
  155. case RM_ANT_CAP_EN:
  156. return "RM_ANT_CAP_EN";
  157. case RM_RSVD:
  158. case RM_MAX:
  159. default:
  160. break;
  161. }
  162. return "unknown";
  163. }
  164. int rm_en_cap_chk_and_set(struct rm_obj *prm, enum rm_cap_en en)
  165. {
  166. int idx;
  167. u8 cap;
  168. if (en >= RM_MAX)
  169. return _FALSE;
  170. idx = en / 8;
  171. cap = prm->psta->padapter->rmpriv.rm_en_cap_def[idx];
  172. if (!(cap & BIT(en - (idx*8)))) {
  173. RTW_INFO("RM: %s incapable\n",rm_en_cap_name(en));
  174. rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);
  175. return _FALSE;
  176. }
  177. return _SUCCESS;
  178. }
  179. static u8 rm_get_oper_class_via_ch(u8 ch)
  180. {
  181. int i,j,sz;
  182. sz = sizeof(RTW_OP_CLASS_US)/sizeof(struct _RT_OPERATING_CLASS);
  183. for (i = 0; i < sz; i++) {
  184. for (j = 0; j < RTW_OP_CLASS_US[i].Len; j++) {
  185. if ( ch == RTW_OP_CLASS_US[i].Channel[j]) {
  186. RTW_INFO("RM: ch %u in oper_calss %u\n",
  187. ch, RTW_OP_CLASS_US[i].global_op_class);
  188. return RTW_OP_CLASS_US[i].global_op_class;
  189. break;
  190. }
  191. }
  192. }
  193. return 0;
  194. }
  195. static u8 rm_get_ch_set(
  196. struct rtw_ieee80211_channel *pch_set, u8 op_class, u8 ch_num)
  197. {
  198. int i,j,sz;
  199. u8 ch_amount = 0;
  200. sz = sizeof(RTW_OP_CLASS_US)/sizeof(struct _RT_OPERATING_CLASS);
  201. if (ch_num != 0) {
  202. pch_set[0].hw_value = ch_num;
  203. ch_amount = 1;
  204. RTW_INFO("RM: meas_ch->hw_value = %u\n", pch_set->hw_value);
  205. goto done;
  206. }
  207. for (i = 0; i < sz; i++) {
  208. if (RTW_OP_CLASS_US[i].global_op_class == op_class) {
  209. for (j = 0; j < RTW_OP_CLASS_US[i].Len; j++) {
  210. pch_set[j].hw_value =
  211. RTW_OP_CLASS_US[i].Channel[j];
  212. RTW_INFO("RM: meas_ch[%d].hw_value = %u\n",
  213. j, pch_set[j].hw_value);
  214. }
  215. ch_amount = RTW_OP_CLASS_US[i].Len;
  216. break;
  217. }
  218. }
  219. done:
  220. return ch_amount;
  221. }
  222. static int is_wildcard_bssid(u8 *bssid)
  223. {
  224. int i;
  225. u8 val8 = 0xff;
  226. for (i=0;i<6;i++)
  227. val8 &= bssid[i];
  228. if (val8 == 0xff)
  229. return _SUCCESS;
  230. return _FALSE;
  231. }
  232. /* for caller outside rm */
  233. u8 rm_add_nb_req(_adapter *padapter, struct sta_info *psta)
  234. {
  235. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  236. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  237. struct rm_obj *prm;
  238. prm = rm_alloc_rmobj(padapter);
  239. if (prm == NULL) {
  240. RTW_ERR("RM: unable to alloc rm obj for requeset\n");
  241. return _FALSE;
  242. }
  243. prm->psta = psta;
  244. prm->q.category = RTW_WLAN_CATEGORY_RADIO_MEAS;
  245. prm->q.diag_token = pmlmeinfo->dialogToken++;
  246. prm->q.m_token = 1;
  247. prm->rmid = psta->cmn.aid << 16
  248. | prm->q.diag_token << 8
  249. | RM_MASTER;
  250. prm->q.action_code = RM_ACT_NB_REP_REQ;
  251. #if 0
  252. if (pmac) { /* find sta_info according to bssid */
  253. pmac += 4; /* skip mac= */
  254. if (hwaddr_parse(pmac, bssid) == NULL) {
  255. sprintf(pstr(s), "Err: \nincorrect mac format\n");
  256. return _FAIL;
  257. }
  258. psta = rm_get_sta(padapter, 0xff, bssid);
  259. }
  260. #endif
  261. /* enquee rmobj */
  262. rm_enqueue_rmobj(padapter, prm, _FALSE);
  263. RTW_INFO("RM: rmid=%x add req to " MAC_FMT "\n",
  264. prm->rmid, MAC_ARG(psta->cmn.mac_addr));
  265. return _SUCCESS;
  266. }
  267. static u8 *build_wlan_hdr(_adapter *padapter, struct xmit_frame *pmgntframe,
  268. struct sta_info *psta, u16 frame_type)
  269. {
  270. u8 *pframe;
  271. u16 *fctrl;
  272. struct pkt_attrib *pattr;
  273. struct rtw_ieee80211_hdr *pwlanhdr;
  274. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  275. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  276. /* update attribute */
  277. pattr = &pmgntframe->attrib;
  278. update_mgntframe_attrib(padapter, pattr);
  279. _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  280. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  281. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  282. fctrl = &(pwlanhdr->frame_ctl);
  283. *(fctrl) = 0;
  284. _rtw_memcpy(pwlanhdr->addr1, psta->cmn.mac_addr, ETH_ALEN);
  285. _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
  286. _rtw_memcpy(pwlanhdr->addr3,
  287. get_my_bssid(&(pmlmeinfo->network)),ETH_ALEN);
  288. RTW_INFO("RM: dst = " MAC_FMT "\n", MAC_ARG(pwlanhdr->addr1));
  289. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  290. pmlmeext->mgnt_seq++;
  291. SetFragNum(pframe, 0);
  292. set_frame_sub_type(pframe, WIFI_ACTION);
  293. pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
  294. pattr->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
  295. return pframe;
  296. }
  297. void rm_set_rep_mode(struct rm_obj *prm, u8 mode)
  298. {
  299. RTW_INFO("RM: rmid=%x set %s\n",
  300. prm->rmid,
  301. mode|MEAS_REP_MOD_INCAP?"INCAP":
  302. mode|MEAS_REP_MOD_REFUSE?"REFUSE":
  303. mode|MEAS_REP_MOD_LATE?"LATE":"");
  304. prm->p.m_mode |= mode;
  305. }
  306. int issue_null_reply(struct rm_obj *prm)
  307. {
  308. int len=0, my_len;
  309. u8 *pframe, m_mode;
  310. _adapter *padapter = prm->psta->padapter;
  311. struct pkt_attrib *pattr;
  312. struct xmit_frame *pmgntframe;
  313. struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
  314. m_mode = prm->p.m_mode;
  315. if (m_mode || prm->p.rpt == 0) {
  316. RTW_INFO("RM: rmid=%x reply (%s repeat=%d)\n",
  317. prm->rmid,
  318. m_mode&MEAS_REP_MOD_INCAP?"INCAP":
  319. m_mode&MEAS_REP_MOD_REFUSE?"REFUSE":
  320. m_mode&MEAS_REP_MOD_LATE?"LATE":"no content",
  321. prm->p.rpt);
  322. }
  323. switch (prm->p.action_code) {
  324. case RM_ACT_RADIO_MEAS_REQ:
  325. len = 8;
  326. break;
  327. case RM_ACT_NB_REP_REQ:
  328. len = 3;
  329. break;
  330. case RM_ACT_LINK_MEAS_REQ:
  331. len = 3;
  332. break;
  333. default:
  334. break;
  335. }
  336. if (len==0)
  337. return _FALSE;
  338. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  339. if (pmgntframe == NULL) {
  340. RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);
  341. return _FALSE;
  342. }
  343. pattr = &pmgntframe->attrib;
  344. pframe = build_wlan_hdr(padapter, pmgntframe, prm->psta, WIFI_ACTION);
  345. pframe = rtw_set_fixed_ie(pframe, 3, &prm->p.category, &pattr->pktlen);
  346. my_len = 0;
  347. if (len>5) {
  348. prm->p.len = len - 3 - 2;
  349. pframe = rtw_set_fixed_ie(pframe, len - 3,
  350. &prm->p.e_id, &my_len);
  351. }
  352. pattr->pktlen += my_len;
  353. pattr->last_txcmdsz = pattr->pktlen;
  354. dump_mgntframe(padapter, pmgntframe);
  355. return _SUCCESS;
  356. }
  357. int ready_for_scan(struct rm_obj *prm)
  358. {
  359. _adapter *padapter = prm->psta->padapter;
  360. u8 ssc_chk;
  361. if (!rtw_is_adapter_up(padapter))
  362. return _FALSE;
  363. ssc_chk = rtw_sitesurvey_condition_check(padapter, _FALSE);
  364. if (ssc_chk == SS_ALLOW)
  365. return _SUCCESS;
  366. return _FALSE;
  367. }
  368. int rm_sitesurvey(struct rm_obj *prm)
  369. {
  370. int meas_ch_num=0;
  371. u8 ch_num=0, op_class=0, val8;
  372. struct rtw_ieee80211_channel *pch_set;
  373. struct sitesurvey_parm parm;
  374. RTW_INFO("RM: rmid=%x %s\n",prm->rmid, __func__);
  375. pch_set = &prm->q.ch_set[0];
  376. _rtw_memset(pch_set, 0,
  377. sizeof(struct rtw_ieee80211_channel) * MAX_OP_CHANNEL_SET_NUM);
  378. if (prm->q.ch_num == 0) {
  379. /* ch_num=0 : scan all ch in operating class */
  380. op_class = prm->q.op_class;
  381. } else if (prm->q.ch_num == 255) {
  382. /* 802.11 p.499 */
  383. /* ch_num=255 : scan all ch in current operating class */
  384. op_class = rm_get_oper_class_via_ch(
  385. (u8)prm->psta->padapter->mlmeextpriv.cur_channel);
  386. } else
  387. ch_num = prm->q.ch_num;
  388. /* get means channel */
  389. meas_ch_num = rm_get_ch_set(pch_set, op_class, ch_num);
  390. prm->q.ch_set_ch_amount = meas_ch_num;
  391. _rtw_memset(&parm, 0, sizeof(struct sitesurvey_parm));
  392. _rtw_memcpy(parm.ch, pch_set,
  393. sizeof(struct rtw_ieee80211_channel) * MAX_OP_CHANNEL_SET_NUM);
  394. _rtw_memcpy(&parm.ssid[0], &prm->q.opt.bcn.ssid, IW_ESSID_MAX_SIZE);
  395. parm.ssid_num = 1;
  396. parm.scan_mode = prm->q.m_mode;
  397. parm.ch_num = meas_ch_num;
  398. parm.igi = 0;
  399. parm.token = prm->rmid;
  400. parm.duration = prm->q.meas_dur;
  401. /* parm.bw = BW_20M; */
  402. rtw_sitesurvey_cmd(prm->psta->padapter, &parm);
  403. return _SUCCESS;
  404. }
  405. static u8 translate_percentage_to_rcpi(u32 SignalStrengthIndex)
  406. {
  407. s32 SignalPower; /* in dBm. */
  408. u8 rcpi;
  409. /* Translate to dBm (x=y-100) */
  410. SignalPower = SignalStrengthIndex - 100;
  411. /* RCPI = Int{(Power in dBm + 110)*2} for 0dBm > Power > -110dBm
  412. * 0 : power <= -110.0 dBm
  413. * 1 : power = -109.5 dBm
  414. * 2 : power = -109.0 dBm
  415. */
  416. rcpi = (SignalPower + 110)*2;
  417. return rcpi;
  418. }
  419. static int rm_parse_ch_load_s_elem(struct rm_obj *prm, u8 *pbody, int req_len)
  420. {
  421. u8 *popt_id;
  422. int i, p=0; /* position */
  423. int len = req_len;
  424. prm->q.opt_s_elem_len = len;
  425. #if (RM_MORE_DBG_MSG)
  426. RTW_INFO("RM: opt_s_elem_len=%d\n", len);
  427. #endif
  428. while (len) {
  429. switch (pbody[p]) {
  430. case ch_load_rep_info:
  431. /* check RM_EN */
  432. rm_en_cap_chk_and_set(prm, RM_CH_LOAD_CAP_EN);
  433. _rtw_memcpy(&(prm->q.opt.clm.rep_cond),
  434. &pbody[p+2], sizeof(prm->q.opt.clm.rep_cond));
  435. RTW_INFO("RM: ch_load_rep_info=%u:%u\n",
  436. prm->q.opt.clm.rep_cond.cond,
  437. prm->q.opt.clm.rep_cond.threshold);
  438. break;
  439. default:
  440. break;
  441. }
  442. len = len - (int)pbody[p+1] - 2;
  443. p = p + (int)pbody[p+1] + 2;
  444. #if (RM_MORE_DBG_MSG)
  445. RTW_INFO("RM: opt_s_elem_len=%d\n",len);
  446. #endif
  447. }
  448. return _SUCCESS;
  449. }
  450. static int rm_parse_noise_histo_s_elem(struct rm_obj *prm,
  451. u8 *pbody, int req_len)
  452. {
  453. u8 *popt_id;
  454. int i, p=0; /* position */
  455. int len = req_len;
  456. prm->q.opt_s_elem_len = len;
  457. #if (RM_MORE_DBG_MSG)
  458. RTW_INFO("RM: opt_s_elem_len=%d\n", len);
  459. #endif
  460. while (len) {
  461. switch (pbody[p]) {
  462. case noise_histo_rep_info:
  463. /* check RM_EN */
  464. rm_en_cap_chk_and_set(prm, RM_NOISE_HISTO_CAP_EN);
  465. _rtw_memcpy(&(prm->q.opt.nhm.rep_cond),
  466. &pbody[p+2], sizeof(prm->q.opt.nhm.rep_cond));
  467. RTW_INFO("RM: noise_histo_rep_info=%u:%u\n",
  468. prm->q.opt.nhm.rep_cond.cond,
  469. prm->q.opt.nhm.rep_cond.threshold);
  470. break;
  471. default:
  472. break;
  473. }
  474. len = len - (int)pbody[p+1] - 2;
  475. p = p + (int)pbody[p+1] + 2;
  476. #if (RM_MORE_DBG_MSG)
  477. RTW_INFO("RM: opt_s_elem_len=%d\n",len);
  478. #endif
  479. }
  480. return _SUCCESS;
  481. }
  482. static int rm_parse_bcn_req_s_elem(struct rm_obj *prm, u8 *pbody, int req_len)
  483. {
  484. u8 *popt_id;
  485. int i, p=0; /* position */
  486. int len = req_len;
  487. /* opt length,2:pbody[0]+ pbody[1] */
  488. /* first opt id : pbody[18] */
  489. prm->q.opt_s_elem_len = len;
  490. #if (RM_MORE_DBG_MSG)
  491. RTW_INFO("RM: opt_s_elem_len=%d\n", len);
  492. #endif
  493. popt_id = prm->q.opt.bcn.opt_id;
  494. while (len && prm->q.opt.bcn.opt_id_num < BCN_REQ_OPT_MAX_NUM) {
  495. switch (pbody[p]) {
  496. case bcn_req_ssid:
  497. RTW_INFO("bcn_req_ssid\n");
  498. #if (DBG_BCN_REQ_WILDCARD)
  499. RTW_INFO("DBG set ssid to WILDCARD\n");
  500. #else
  501. #if (DBG_BCN_REQ_SSID)
  502. RTW_INFO("DBG set ssid to %s\n",DBG_BCN_REQ_SSID_NAME);
  503. i = strlen(DBG_BCN_REQ_SSID_NAME);
  504. prm->q.opt.bcn.ssid.SsidLength = i;
  505. _rtw_memcpy(&(prm->q.opt.bcn.ssid.Ssid),
  506. DBG_BCN_REQ_SSID_NAME, i);
  507. #else /* original */
  508. prm->q.opt.bcn.ssid.SsidLength = pbody[p+1];
  509. _rtw_memcpy(&(prm->q.opt.bcn.ssid.Ssid),
  510. &pbody[p+2], pbody[p+1]);
  511. #endif
  512. #endif
  513. RTW_INFO("RM: bcn_req_ssid=%s\n",
  514. prm->q.opt.bcn.ssid.Ssid);
  515. popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];
  516. break;
  517. case bcn_req_rep_info:
  518. /* check RM_EN */
  519. rm_en_cap_chk_and_set(prm, RM_BCN_MEAS_REP_COND_CAP_EN);
  520. _rtw_memcpy(&(prm->q.opt.bcn.rep_cond),
  521. &pbody[p+2], sizeof(prm->q.opt.bcn.rep_cond));
  522. RTW_INFO("bcn_req_rep_info=%u:%u\n",
  523. prm->q.opt.bcn.rep_cond.cond,
  524. prm->q.opt.bcn.rep_cond.threshold);
  525. /*popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];*/
  526. break;
  527. case bcn_req_rep_detail:
  528. #if DBG_BCN_REQ_DETAIL
  529. prm->q.opt.bcn.rep_detail = 2; /* all IE in beacon */
  530. #else
  531. prm->q.opt.bcn.rep_detail = pbody[p+2];
  532. #endif
  533. popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];
  534. #if (RM_MORE_DBG_MSG)
  535. RTW_INFO("RM: report_detail=%d\n",
  536. prm->q.opt.bcn.rep_detail);
  537. #endif
  538. break;
  539. case bcn_req_req:
  540. RTW_INFO("RM: bcn_req_req\n");
  541. prm->q.opt.bcn.req_start = rtw_malloc(pbody[p+1]);
  542. if (prm->q.opt.bcn.req_start == NULL) {
  543. RTW_ERR("RM: req_start malloc fail!!\n");
  544. break;
  545. }
  546. for (i = 0; i < pbody[p+1]; i++)
  547. *((prm->q.opt.bcn.req_start)+i) =
  548. pbody[p+2+i];
  549. prm->q.opt.bcn.req_len = pbody[p+1];
  550. popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];
  551. break;
  552. case bcn_req_ac_ch_rep:
  553. #if (RM_MORE_DBG_MSG)
  554. RTW_INFO("RM: bcn_req_ac_ch_rep\n");
  555. #endif
  556. popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];
  557. break;
  558. default:
  559. break;
  560. }
  561. len = len - (int)pbody[p+1] - 2;
  562. p = p + (int)pbody[p+1] + 2;
  563. #if (RM_MORE_DBG_MSG)
  564. RTW_INFO("RM: opt_s_elem_len=%d\n",len);
  565. #endif
  566. }
  567. return _SUCCESS;
  568. }
  569. static int rm_parse_meas_req(struct rm_obj *prm, u8 *pbody)
  570. {
  571. int p; /* position */
  572. int req_len;
  573. req_len = (int)pbody[1];
  574. p = 5;
  575. prm->q.op_class = pbody[p++];
  576. prm->q.ch_num = pbody[p++];
  577. prm->q.rand_intvl = le16_to_cpu(*(u16*)(&pbody[p]));
  578. p+=2;
  579. prm->q.meas_dur = le16_to_cpu(*(u16*)(&pbody[p]));
  580. p+=2;
  581. if (prm->q.m_type == bcn_req) {
  582. /*
  583. * 0: passive
  584. * 1: active
  585. * 2: bcn_table
  586. */
  587. prm->q.m_mode = pbody[p++];
  588. /* BSSID */
  589. _rtw_memcpy(&(prm->q.bssid), &pbody[p], 6);
  590. p+=6;
  591. /*
  592. * default, used when Reporting detail subelement
  593. * is not included in Beacon Request
  594. */
  595. prm->q.opt.bcn.rep_detail = 2;
  596. }
  597. if (req_len-(p-2) <= 0) /* without sub-element */
  598. return _SUCCESS;
  599. switch (prm->q.m_type) {
  600. case bcn_req:
  601. rm_parse_bcn_req_s_elem(prm, &pbody[p], req_len-(p-2));
  602. break;
  603. case ch_load_req:
  604. rm_parse_ch_load_s_elem(prm, &pbody[p], req_len-(p-2));
  605. break;
  606. case noise_histo_req:
  607. rm_parse_noise_histo_s_elem(prm, &pbody[p], req_len-(p-2));
  608. break;
  609. default:
  610. break;
  611. }
  612. return _SUCCESS;
  613. }
  614. /* receive measurement request */
  615. int rm_recv_radio_mens_req(_adapter *padapter,
  616. union recv_frame *precv_frame, struct sta_info *psta)
  617. {
  618. struct rm_obj *prm;
  619. struct rm_priv *prmpriv = &padapter->rmpriv;
  620. u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +
  621. sizeof(struct rtw_ieee80211_hdr_3addr));
  622. u8 *pmeas_body = &pdiag_body[5];
  623. u8 rmid, update = 0;
  624. #if 0
  625. /* search existing rm_obj */
  626. rmid = psta->cmn.aid << 16
  627. | pdiag_body[2] << 8
  628. | RM_SLAVE;
  629. prm = rm_get_rmobj(padapter, rmid);
  630. if (prm) {
  631. RTW_INFO("RM: Found an exist meas rmid=%u\n", rmid);
  632. update = 1;
  633. } else
  634. #endif
  635. prm = rm_alloc_rmobj(padapter);
  636. if (prm == NULL) {
  637. RTW_ERR("RM: unable to alloc rm obj for requeset\n");
  638. return _FALSE;
  639. }
  640. prm->psta = psta;
  641. prm->q.diag_token = pdiag_body[2];
  642. prm->q.rpt = le16_to_cpu(*(u16*)(&pdiag_body[3]));
  643. /* Figure 8-104 Measurement Requested format */
  644. prm->q.e_id = pmeas_body[0];
  645. prm->q.m_token = pmeas_body[2];
  646. prm->q.m_mode = pmeas_body[3];
  647. prm->q.m_type = pmeas_body[4];
  648. prm->rmid = psta->cmn.aid << 16
  649. | prm->q.diag_token << 8
  650. | RM_SLAVE;
  651. RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,
  652. MAC_ARG(prm->psta->cmn.mac_addr));
  653. #if (RM_MORE_DBG_MSG)
  654. RTW_INFO("RM: element_id = %d\n", prm->q.e_id);
  655. RTW_INFO("RM: length = %d\n", (int)pmeas_body[1]);
  656. RTW_INFO("RM: meas_token = %d\n", prm->q.m_token);
  657. RTW_INFO("RM: meas_mode = %d\n", prm->q.m_mode);
  658. RTW_INFO("RM: meas_type = %d\n", prm->q.m_type);
  659. #endif
  660. if (prm->q.e_id != _MEAS_REQ_IE_) /* 38 */
  661. return _FALSE;
  662. switch (prm->q.m_type) {
  663. case bcn_req:
  664. RTW_INFO("RM: recv beacon_request\n");
  665. switch (prm->q.m_mode) {
  666. case bcn_req_passive:
  667. rm_en_cap_chk_and_set(prm, RM_BCN_PASSIVE_MEAS_CAP_EN);
  668. break;
  669. case bcn_req_active:
  670. rm_en_cap_chk_and_set(prm, RM_BCN_ACTIVE_MEAS_CAP_EN);
  671. break;
  672. case bcn_req_bcn_table:
  673. rm_en_cap_chk_and_set(prm, RM_BCN_TABLE_MEAS_CAP_EN);
  674. break;
  675. default:
  676. rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);
  677. break;
  678. }
  679. break;
  680. case ch_load_req:
  681. RTW_INFO("RM: recv ch_load_request\n");
  682. rm_en_cap_chk_and_set(prm, RM_CH_LOAD_CAP_EN);
  683. break;
  684. case noise_histo_req:
  685. RTW_INFO("RM: recv noise_histogram_request\n");
  686. rm_en_cap_chk_and_set(prm, RM_NOISE_HISTO_CAP_EN);
  687. break;
  688. default:
  689. RTW_INFO("RM: recv unknown request type 0x%02x\n",
  690. prm->q.m_type);
  691. rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);
  692. goto done;
  693. }
  694. rm_parse_meas_req(prm, pmeas_body);
  695. done:
  696. if (!update)
  697. rm_enqueue_rmobj(padapter, prm, _FALSE);
  698. return _SUCCESS;
  699. }
  700. /* receive measurement report */
  701. int rm_recv_radio_mens_rep(_adapter *padapter,
  702. union recv_frame *precv_frame, struct sta_info *psta)
  703. {
  704. int ret = _FALSE;
  705. struct rm_obj *prm;
  706. u32 rmid;
  707. u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +
  708. sizeof(struct rtw_ieee80211_hdr_3addr));
  709. u8 *pmeas_body = &pdiag_body[3];
  710. rmid = psta->cmn.aid << 16
  711. | pdiag_body[2] << 8
  712. | RM_MASTER;
  713. prm = rm_get_rmobj(padapter, rmid);
  714. if (prm == NULL)
  715. return _FALSE;
  716. prm->p.action_code = pdiag_body[1];
  717. prm->p.diag_token = pdiag_body[2];
  718. /* Figure 8-140 Measuremnt Report format */
  719. prm->p.e_id = pmeas_body[0];
  720. prm->p.m_token = pmeas_body[2];
  721. prm->p.m_mode = pmeas_body[3];
  722. prm->p.m_type = pmeas_body[4];
  723. RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,
  724. MAC_ARG(prm->psta->cmn.mac_addr));
  725. #if (RM_MORE_DBG_MSG)
  726. RTW_INFO("RM: element_id = %d\n", prm->p.e_id);
  727. RTW_INFO("RM: length = %d\n", (int)pmeas_body[1]);
  728. RTW_INFO("RM: meas_token = %d\n", prm->p.m_token);
  729. RTW_INFO("RM: meas_mode = %d\n", prm->p.m_mode);
  730. RTW_INFO("RM: meas_type = %d\n", prm->p.m_type);
  731. #endif
  732. if (prm->p.e_id != _MEAS_RSP_IE_) /* 39 */
  733. return _FALSE;
  734. RTW_INFO("RM: recv %s\n", rm_type_rep_name(prm->p.m_type));
  735. rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);
  736. return ret;
  737. }
  738. int rm_radio_mens_nb_rep(_adapter *padapter,
  739. union recv_frame *precv_frame, struct sta_info *psta)
  740. {
  741. u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +
  742. sizeof(struct rtw_ieee80211_hdr_3addr));
  743. u8 *pmeas_body = &pdiag_body[3];
  744. u32 len = precv_frame->u.hdr.len;
  745. u32 rmid;
  746. struct rm_obj *prm;
  747. rmid = psta->cmn.aid << 16
  748. | pdiag_body[2] << 8
  749. | RM_MASTER;
  750. prm = rm_get_rmobj(padapter, rmid);
  751. if (prm == NULL)
  752. return _FALSE;
  753. prm->p.action_code = pdiag_body[1];
  754. prm->p.diag_token = pdiag_body[2];
  755. prm->p.e_id = pmeas_body[0];
  756. RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,
  757. MAC_ARG(prm->psta->cmn.mac_addr));
  758. #if (RM_MORE_DBG_MSG)
  759. RTW_INFO("RM: element_id = %d\n", prm->p.e_id);
  760. RTW_INFO("RM: length = %d\n", (int)pmeas_body[1]);
  761. #endif
  762. rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);
  763. #ifdef CONFIG_LAYER2_ROAMING
  764. if (rtw_wnm_btm_candidates_survey(padapter
  765. ,(pdiag_body + 3)
  766. ,(len - sizeof(struct rtw_ieee80211_hdr_3addr))
  767. ,_FALSE) == _FAIL)
  768. return _FALSE;
  769. #endif
  770. rtw_cfg80211_rx_rrm_action(padapter, precv_frame);
  771. return _TRUE;
  772. }
  773. unsigned int rm_on_action(_adapter *padapter, union recv_frame *precv_frame)
  774. {
  775. u32 ret = _FAIL;
  776. u8 *pframe = NULL;
  777. u8 *pframe_body = NULL;
  778. u8 action_code = 0;
  779. u8 diag_token = 0;
  780. struct rtw_ieee80211_hdr_3addr *whdr;
  781. struct sta_info *psta;
  782. pframe = precv_frame->u.hdr.rx_data;
  783. /* check RA matches or not */
  784. if (!_rtw_memcmp(adapter_mac_addr(padapter),
  785. GetAddr1Ptr(pframe), ETH_ALEN))
  786. goto exit;
  787. whdr = (struct rtw_ieee80211_hdr_3addr *)pframe;
  788. RTW_INFO("RM: %s bssid = " MAC_FMT "\n",
  789. __func__, MAC_ARG(whdr->addr2));
  790. psta = rtw_get_stainfo(&padapter->stapriv, whdr->addr2);
  791. if (!psta) {
  792. RTW_ERR("RM: psta not found\n");
  793. goto exit;
  794. }
  795. pframe_body = (unsigned char *)(pframe +
  796. sizeof(struct rtw_ieee80211_hdr_3addr));
  797. /* Figure 8-438 radio measurement request frame Action field format */
  798. /* Category = pframe_body[0] = 5 (Radio Measurement) */
  799. action_code = pframe_body[1];
  800. diag_token = pframe_body[2];
  801. #if (RM_MORE_DBG_MSG)
  802. RTW_INFO("RM: %s radio_action=%x, diag_token=%x\n", __func__,
  803. action_code, diag_token);
  804. #endif
  805. switch (action_code) {
  806. case RM_ACT_RADIO_MEAS_REQ:
  807. RTW_INFO("RM: RM_ACT_RADIO_MEAS_REQ\n");
  808. ret = rm_recv_radio_mens_req(padapter, precv_frame, psta);
  809. break;
  810. case RM_ACT_RADIO_MEAS_REP:
  811. RTW_INFO("RM: RM_ACT_RADIO_MEAS_REP\n");
  812. ret = rm_recv_radio_mens_rep(padapter, precv_frame, psta);
  813. break;
  814. case RM_ACT_LINK_MEAS_REQ:
  815. RTW_INFO("RM: RM_ACT_LINK_MEAS_REQ\n");
  816. break;
  817. case RM_ACT_LINK_MEAS_REP:
  818. RTW_INFO("RM: RM_ACT_LINK_MEAS_REP\n");
  819. break;
  820. case RM_ACT_NB_REP_REQ:
  821. RTW_INFO("RM: RM_ACT_NB_REP_REQ\n");
  822. break;
  823. case RM_ACT_NB_REP_RESP:
  824. RTW_INFO("RM: RM_ACT_NB_REP_RESP\n");
  825. ret = rm_radio_mens_nb_rep(padapter, precv_frame, psta);
  826. break;
  827. default:
  828. /* TODO reply incabable */
  829. RTW_ERR("RM: unknown specturm management action %2x\n",
  830. action_code);
  831. break;
  832. }
  833. exit:
  834. return ret;
  835. }
  836. static u8 *rm_gen_bcn_detail_elem(_adapter *padapter, u8 *pframe,
  837. struct rm_obj *prm, struct wlan_network *pnetwork,
  838. unsigned int *fr_len)
  839. {
  840. WLAN_BSSID_EX *pbss = &pnetwork->network;
  841. unsigned int my_len;
  842. int j, k, len;
  843. u8 *plen;
  844. u8 *ptr;
  845. u8 val8, eid;
  846. my_len = 0;
  847. /* Reporting Detail values
  848. * 0: No fixed length fields or elements
  849. * 1: All fixed length fields and any requested elements
  850. * in the Request info element if present
  851. * 2: All fixed length fields and elements
  852. * 3-255: Reserved
  853. */
  854. /* report_detail = 0 */
  855. if (prm->q.opt.bcn.rep_detail == 0
  856. || prm->q.opt.bcn.rep_detail > 2) {
  857. return pframe;
  858. }
  859. /* ID */
  860. val8 = 1; /* 1:reported frame body */
  861. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  862. plen = pframe;
  863. val8 = 0;
  864. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  865. /* report_detail = 2 */
  866. if (prm->q.opt.bcn.rep_detail == 2) {
  867. pframe = rtw_set_fixed_ie(pframe, pbss->IELength - 4,
  868. pbss->IEs, &my_len); /* -4 remove FCS */
  869. goto done;
  870. }
  871. /* report_detail = 1 */
  872. /* all fixed lenght fields */
  873. pframe = rtw_set_fixed_ie(pframe,
  874. _FIXED_IE_LENGTH_, pbss->IEs, &my_len);
  875. for (j = 0; j < prm->q.opt.bcn.opt_id_num; j++) {
  876. switch (prm->q.opt.bcn.opt_id[j]) {
  877. case bcn_req_ssid:
  878. /* SSID */
  879. #if (RM_MORE_DBG_MSG)
  880. RTW_INFO("RM: bcn_req_ssid\n");
  881. #endif
  882. pframe = rtw_set_ie(pframe, _SSID_IE_,
  883. pbss->Ssid.SsidLength,
  884. pbss->Ssid.Ssid, &my_len);
  885. break;
  886. case bcn_req_req:
  887. if (prm->q.opt.bcn.req_start == NULL)
  888. break;
  889. #if (RM_MORE_DBG_MSG)
  890. RTW_INFO("RM: bcn_req_req");
  891. #endif
  892. for (k=0; k<prm->q.opt.bcn.req_len; k++) {
  893. eid = prm->q.opt.bcn.req_start[k];
  894. val8 = pbss->IELength - _FIXED_IE_LENGTH_;
  895. ptr = rtw_get_ie(pbss->IEs + _FIXED_IE_LENGTH_,
  896. eid, &len, val8);
  897. if (!ptr)
  898. continue;
  899. #if (RM_MORE_DBG_MSG)
  900. switch (eid) {
  901. case EID_QBSSLoad:
  902. RTW_INFO("RM: EID_QBSSLoad\n");
  903. break;
  904. case EID_HTCapability:
  905. RTW_INFO("RM: EID_HTCapability\n");
  906. break;
  907. case _MDIE_:
  908. RTW_INFO("RM: EID_MobilityDomain\n");
  909. break;
  910. default:
  911. RTW_INFO("RM: EID %d todo\n",eid);
  912. break;
  913. }
  914. #endif
  915. pframe = rtw_set_ie(pframe, eid,
  916. len,ptr+2, &my_len);
  917. } /* for() */
  918. break;
  919. case bcn_req_ac_ch_rep:
  920. default:
  921. RTW_INFO("RM: OPT %d TODO\n",prm->q.opt.bcn.opt_id[j]);
  922. break;
  923. }
  924. }
  925. done:
  926. /*
  927. * update my length
  928. * content length does NOT include ID and LEN
  929. */
  930. val8 = my_len - 2;
  931. rtw_set_fixed_ie(plen, 1, &val8, &j);
  932. /* update length to caller */
  933. *fr_len += my_len;
  934. return pframe;
  935. }
  936. static u8 rm_get_rcpi(struct rm_obj *prm, struct wlan_network *pnetwork)
  937. {
  938. return translate_percentage_to_rcpi(
  939. pnetwork->network.PhyInfo.SignalStrength);
  940. }
  941. static u8 rm_get_rsni(struct rm_obj *prm, struct wlan_network *pnetwork)
  942. {
  943. int i;
  944. u8 val8, snr;
  945. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(prm->psta->padapter);
  946. if (pnetwork->network.PhyInfo.is_cck_rate) {
  947. /* current HW doesn't have CCK RSNI */
  948. /* 255 indicates RSNI is unavailable */
  949. val8 = 255;
  950. } else {
  951. snr = 0;
  952. for (i = 0; i < pHalData->NumTotalRFPath; i++) {
  953. snr += pnetwork->network.PhyInfo.rx_snr[i];
  954. }
  955. snr = snr / pHalData->NumTotalRFPath;
  956. val8 = (u8)(snr + 10)*2;
  957. }
  958. return val8;
  959. }
  960. u8 rm_bcn_req_cond_mach(struct rm_obj *prm, struct wlan_network *pnetwork)
  961. {
  962. u8 val8;
  963. switch(prm->q.opt.bcn.rep_cond.cond) {
  964. case bcn_rep_cond_immediately:
  965. return _SUCCESS;
  966. case bcn_req_cond_rcpi_greater:
  967. val8 = rm_get_rcpi(prm, pnetwork);
  968. if (val8 > prm->q.opt.bcn.rep_cond.threshold)
  969. return _SUCCESS;
  970. break;
  971. case bcn_req_cond_rcpi_less:
  972. val8 = rm_get_rcpi(prm, pnetwork);
  973. if (val8 < prm->q.opt.bcn.rep_cond.threshold)
  974. return _SUCCESS;
  975. break;
  976. case bcn_req_cond_rsni_greater:
  977. val8 = rm_get_rsni(prm, pnetwork);
  978. if (val8 != 255 && val8 > prm->q.opt.bcn.rep_cond.threshold)
  979. return _SUCCESS;
  980. break;
  981. case bcn_req_cond_rsni_less:
  982. val8 = rm_get_rsni(prm, pnetwork);
  983. if (val8 != 255 && val8 < prm->q.opt.bcn.rep_cond.threshold)
  984. return _SUCCESS;
  985. break;
  986. default:
  987. RTW_ERR("RM: bcn_req cond %u not support\n",
  988. prm->q.opt.bcn.rep_cond.cond);
  989. break;
  990. }
  991. return _FALSE;
  992. }
  993. static u8 *rm_bcn_rep_fill_scan_resule (struct rm_obj *prm,
  994. u8 *pframe, struct wlan_network *pnetwork, unsigned int *fr_len)
  995. {
  996. int snr, i;
  997. u8 val8, *plen;
  998. u16 val16;
  999. u32 val32;
  1000. u64 val64;
  1001. PWLAN_BSSID_EX pbss;
  1002. unsigned int my_len;
  1003. _adapter *padapter = prm->psta->padapter;
  1004. my_len = 0;
  1005. /* meas ID */
  1006. val8 = EID_MeasureReport;
  1007. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1008. /* remember position form elelment length */
  1009. plen = pframe;
  1010. /* meas_rpt_len */
  1011. /* default 3 = mode + token + type but no beacon content */
  1012. val8 = 3;
  1013. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1014. /* meas_token */
  1015. val8 = prm->q.m_token;
  1016. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1017. /* meas_rpt_mode F8-141 */
  1018. val8 = prm->p.m_mode;
  1019. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1020. /* meas_type T8-81 */
  1021. val8 = bcn_rep;
  1022. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1023. if (pnetwork == NULL)
  1024. goto done;
  1025. pframe = rtw_set_fixed_ie(pframe, 1, &prm->q.op_class, &my_len);
  1026. /* channel */
  1027. pbss = &pnetwork->network;
  1028. val8 = pbss->Configuration.DSConfig;
  1029. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1030. /* Actual Measurement StartTime */
  1031. val64 = cpu_to_le64(prm->meas_start_time);
  1032. pframe = rtw_set_fixed_ie(pframe, 8, (u8 *)&val64, &my_len);
  1033. /* Measurement Duration */
  1034. val16 = prm->meas_end_time - prm->meas_start_time;
  1035. val16 = cpu_to_le16(val16);
  1036. pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
  1037. /* TODO
  1038. * ReportedFrameInformation:
  1039. * 0 :beacon or probe rsp
  1040. * 1 :pilot frame
  1041. */
  1042. val8 = 0; /* report frame info */
  1043. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1044. /* RCPI */
  1045. val8 = rm_get_rcpi(prm, pnetwork);
  1046. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1047. /* RSNI */
  1048. val8 = rm_get_rsni(prm, pnetwork);
  1049. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1050. /* BSSID */
  1051. pframe = rtw_set_fixed_ie(pframe, 6, (u8 *)&pbss->MacAddress, &my_len);
  1052. /*
  1053. * AntennaID
  1054. * 0: unknown
  1055. * 255: multiple antenna (Diversity)
  1056. */
  1057. val8 = 0;
  1058. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1059. /* ParentTSF */
  1060. val32 = prm->meas_start_time + pnetwork->network.PhyInfo.free_cnt;
  1061. pframe = rtw_set_fixed_ie(pframe, 4, (u8 *)&val32, &my_len);
  1062. /*
  1063. * Generate Beacon detail
  1064. */
  1065. pframe = rm_gen_bcn_detail_elem(padapter, pframe,
  1066. prm, pnetwork, &my_len);
  1067. done:
  1068. /*
  1069. * update my length
  1070. * content length does NOT include ID and LEN
  1071. */
  1072. val8 = my_len - 2;
  1073. rtw_set_fixed_ie(plen, 1, &val8, &i);
  1074. /* update length to caller */
  1075. *fr_len += my_len;
  1076. return pframe;
  1077. }
  1078. static u8 *rm_gen_bcn_rep_ie (struct rm_obj *prm,
  1079. u8 *pframe, struct wlan_network *pnetwork, unsigned int *fr_len)
  1080. {
  1081. int snr, i;
  1082. u8 val8, *plen;
  1083. u16 val16;
  1084. u32 val32;
  1085. u64 val64;
  1086. unsigned int my_len;
  1087. _adapter *padapter = prm->psta->padapter;
  1088. my_len = 0;
  1089. plen = pframe + 1;
  1090. pframe = rtw_set_fixed_ie(pframe, 7, &prm->p.e_id, &my_len);
  1091. /* Actual Measurement StartTime */
  1092. val64 = cpu_to_le64(prm->meas_start_time);
  1093. pframe = rtw_set_fixed_ie(pframe, 8, (u8 *)&val64, &my_len);
  1094. /* Measurement Duration */
  1095. val16 = prm->meas_end_time - prm->meas_start_time;
  1096. val16 = cpu_to_le16(val16);
  1097. pframe = rtw_set_fixed_ie(pframe, 2, (u8*)&val16, &my_len);
  1098. /* TODO
  1099. * ReportedFrameInformation:
  1100. * 0 :beacon or probe rsp
  1101. * 1 :pilot frame
  1102. */
  1103. val8 = 0; /* report frame info */
  1104. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1105. /* RCPI */
  1106. val8 = rm_get_rcpi(prm, pnetwork);
  1107. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1108. /* RSNI */
  1109. val8 = rm_get_rsni(prm, pnetwork);
  1110. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1111. /* BSSID */
  1112. pframe = rtw_set_fixed_ie(pframe, 6,
  1113. (u8 *)&pnetwork->network.MacAddress, &my_len);
  1114. /*
  1115. * AntennaID
  1116. * 0: unknown
  1117. * 255: multiple antenna (Diversity)
  1118. */
  1119. val8 = 0;
  1120. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1121. /* ParentTSF */
  1122. val32 = prm->meas_start_time + pnetwork->network.PhyInfo.free_cnt;
  1123. pframe = rtw_set_fixed_ie(pframe, 4, (u8 *)&val32, &my_len);
  1124. /* Generate Beacon detail */
  1125. pframe = rm_gen_bcn_detail_elem(padapter, pframe,
  1126. prm, pnetwork, &my_len);
  1127. done:
  1128. /*
  1129. * update my length
  1130. * content length does NOT include ID and LEN
  1131. */
  1132. val8 = my_len - 2;
  1133. rtw_set_fixed_ie(plen, 1, &val8, &i);
  1134. /* update length to caller */
  1135. *fr_len += my_len;
  1136. return pframe;
  1137. }
  1138. static int retrieve_scan_result(struct rm_obj *prm)
  1139. {
  1140. _irqL irqL;
  1141. _list *plist, *phead;
  1142. _queue *queue;
  1143. _adapter *padapter = prm->psta->padapter;
  1144. struct rtw_ieee80211_channel *pch_set;
  1145. struct wlan_network *pnetwork = NULL;
  1146. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  1147. int i, meas_ch_num=0;
  1148. PWLAN_BSSID_EX pbss;
  1149. unsigned int matched_network;
  1150. int len, my_len;
  1151. u8 buf_idx, *pbuf = NULL, *tmp_buf = NULL;
  1152. tmp_buf = rtw_malloc(MAX_XMIT_EXTBUF_SZ);
  1153. if (tmp_buf == NULL)
  1154. return 0;
  1155. my_len = 0;
  1156. buf_idx = 0;
  1157. matched_network = 0;
  1158. queue = &(pmlmepriv->scanned_queue);
  1159. _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
  1160. phead = get_list_head(queue);
  1161. plist = get_next(phead);
  1162. /* get requested measurement channel set */
  1163. pch_set = prm->q.ch_set;
  1164. meas_ch_num = prm->q.ch_set_ch_amount;
  1165. /* search scan queue to find requested SSID */
  1166. while (1) {
  1167. if (rtw_end_of_queue_search(phead, plist) == _TRUE)
  1168. break;
  1169. pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
  1170. pbss = &pnetwork->network;
  1171. /*
  1172. * report network if requested channel set contains
  1173. * the channel matchs selected network
  1174. */
  1175. if (rtw_chset_search_ch(adapter_to_chset(padapter),
  1176. pbss->Configuration.DSConfig) == 0)
  1177. goto next;
  1178. if (rtw_mlme_band_check(padapter, pbss->Configuration.DSConfig)
  1179. == _FALSE)
  1180. goto next;
  1181. if (rtw_validate_ssid(&(pbss->Ssid)) == _FALSE)
  1182. goto next;
  1183. /* go through measurement requested channels */
  1184. for (i = 0; i < meas_ch_num; i++) {
  1185. /* match channel */
  1186. if (pch_set[i].hw_value != pbss->Configuration.DSConfig)
  1187. continue;
  1188. /* match bssid */
  1189. if (is_wildcard_bssid(prm->q.bssid) == FALSE)
  1190. if (_rtw_memcmp(prm->q.bssid,
  1191. pbss->MacAddress, 6) == _FALSE) {
  1192. continue;
  1193. }
  1194. /*
  1195. * default wildcard SSID. wildcard SSID:
  1196. * A SSID value (null) used to represent all SSIDs
  1197. */
  1198. /* match ssid */
  1199. if ((prm->q.opt.bcn.ssid.SsidLength > 0) &&
  1200. _rtw_memcmp(prm->q.opt.bcn.ssid.Ssid,
  1201. pbss->Ssid.Ssid,
  1202. prm->q.opt.bcn.ssid.SsidLength) == _FALSE)
  1203. continue;
  1204. /* match condition */
  1205. if (rm_bcn_req_cond_mach(prm, pnetwork) == _FALSE) {
  1206. RTW_INFO("RM: condition mismatch ch %u ssid %s bssid "MAC_FMT"\n",
  1207. pch_set[i].hw_value, pbss->Ssid.Ssid,
  1208. MAC_ARG(pbss->MacAddress));
  1209. RTW_INFO("RM: condition %u:%u\n",
  1210. prm->q.opt.bcn.rep_cond.cond,
  1211. prm->q.opt.bcn.rep_cond.threshold);
  1212. continue;
  1213. }
  1214. /* Found a matched SSID */
  1215. matched_network++;
  1216. RTW_INFO("RM: ch %u Found %s bssid "MAC_FMT"\n",
  1217. pch_set[i].hw_value, pbss->Ssid.Ssid,
  1218. MAC_ARG(pbss->MacAddress));
  1219. len = 0;
  1220. _rtw_memset(tmp_buf, 0, MAX_XMIT_EXTBUF_SZ);
  1221. rm_gen_bcn_rep_ie(prm, tmp_buf, pnetwork, &len);
  1222. new_packet:
  1223. if (my_len == 0) {
  1224. pbuf = rtw_malloc(MAX_XMIT_EXTBUF_SZ);
  1225. if (pbuf == NULL)
  1226. goto fail;
  1227. prm->buf[buf_idx].pbuf = pbuf;
  1228. }
  1229. if ((MAX_XMIT_EXTBUF_SZ - (my_len+len+24+4)) > 0) {
  1230. pbuf = rtw_set_fixed_ie(pbuf,
  1231. len, tmp_buf, &my_len);
  1232. prm->buf[buf_idx].len = my_len;
  1233. } else {
  1234. if (my_len == 0) /* not enough space */
  1235. goto fail;
  1236. my_len = 0;
  1237. buf_idx++;
  1238. goto new_packet;
  1239. }
  1240. } /* for() */
  1241. next:
  1242. plist = get_next(plist);
  1243. } /* while() */
  1244. fail:
  1245. _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
  1246. if (tmp_buf)
  1247. rtw_mfree(tmp_buf, MAX_XMIT_EXTBUF_SZ);
  1248. RTW_INFO("RM: Found %d matched %s\n", matched_network,
  1249. prm->q.opt.bcn.ssid.Ssid);
  1250. if (prm->buf[buf_idx].pbuf)
  1251. return buf_idx+1;
  1252. return 0;
  1253. }
  1254. int issue_beacon_rep(struct rm_obj *prm)
  1255. {
  1256. int i, my_len;
  1257. u8 *pframe;
  1258. _adapter *padapter = prm->psta->padapter;
  1259. struct pkt_attrib *pattr;
  1260. struct xmit_frame *pmgntframe;
  1261. struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
  1262. int pkt_num;
  1263. pkt_num = retrieve_scan_result(prm);
  1264. if (pkt_num == 0) {
  1265. issue_null_reply(prm);
  1266. return _SUCCESS;
  1267. }
  1268. for (i=0;i<pkt_num;i++) {
  1269. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  1270. if (pmgntframe == NULL) {
  1271. RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);
  1272. goto fail;
  1273. }
  1274. pattr = &pmgntframe->attrib;
  1275. pframe = build_wlan_hdr(padapter,
  1276. pmgntframe, prm->psta, WIFI_ACTION);
  1277. pframe = rtw_set_fixed_ie(pframe,
  1278. 3, &prm->p.category, &pattr->pktlen);
  1279. my_len = 0;
  1280. pframe = rtw_set_fixed_ie(pframe,
  1281. prm->buf[i].len, prm->buf[i].pbuf, &my_len);
  1282. pattr->pktlen += my_len;
  1283. pattr->last_txcmdsz = pattr->pktlen;
  1284. dump_mgntframe(padapter, pmgntframe);
  1285. }
  1286. fail:
  1287. for (i=0;i<pkt_num;i++) {
  1288. if (prm->buf[i].pbuf) {
  1289. rtw_mfree(prm->buf[i].pbuf, MAX_XMIT_EXTBUF_SZ);
  1290. prm->buf[i].pbuf = NULL;
  1291. prm->buf[i].len = 0;
  1292. }
  1293. }
  1294. return _SUCCESS;
  1295. }
  1296. /* neighbor request */
  1297. int issue_nb_req(struct rm_obj *prm)
  1298. {
  1299. _adapter *padapter = prm->psta->padapter;
  1300. struct sta_info *psta = prm->psta;
  1301. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  1302. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  1303. struct xmit_frame *pmgntframe = NULL;
  1304. struct pkt_attrib *pattr = NULL;
  1305. u8 val8;
  1306. u8 *pframe = NULL;
  1307. RTW_INFO("RM: %s\n", __func__);
  1308. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  1309. if (pmgntframe == NULL) {
  1310. RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);
  1311. return _FALSE;
  1312. }
  1313. pattr = &pmgntframe->attrib;
  1314. pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);
  1315. pframe = rtw_set_fixed_ie(pframe,
  1316. 3, &prm->q.category, &pattr->pktlen);
  1317. if (prm->q.pssid) {
  1318. u8 sub_ie[64] = {0};
  1319. u8 *pie = &sub_ie[2];
  1320. RTW_INFO("RM: Send NB Req to "MAC_FMT" for(SSID) %s searching\n",
  1321. MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
  1322. pmlmepriv->cur_network.network.Ssid.Ssid);
  1323. val8 = strlen(prm->q.pssid);
  1324. sub_ie[0] = 0; /*SSID*/
  1325. sub_ie[1] = val8;
  1326. _rtw_memcpy(pie, prm->q.pssid, val8);
  1327. pframe = rtw_set_fixed_ie(pframe, val8 + 2,
  1328. sub_ie, &pattr->pktlen);
  1329. } else {
  1330. if (!pmlmepriv->cur_network.network.Ssid.SsidLength)
  1331. RTW_INFO("RM: Send NB Req to "MAC_FMT"\n",
  1332. MAC_ARG(pmlmepriv->cur_network.network.MacAddress));
  1333. else {
  1334. u8 sub_ie[64] = {0};
  1335. u8 *pie = &sub_ie[2];
  1336. RTW_INFO("RM: Send NB Req to "MAC_FMT" for(SSID) %s searching\n",
  1337. MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
  1338. pmlmepriv->cur_network.network.Ssid.Ssid);
  1339. sub_ie[0] = 0; /*SSID*/
  1340. sub_ie[1] = pmlmepriv->cur_network.network.Ssid.SsidLength;
  1341. _rtw_memcpy(pie, pmlmepriv->cur_network.network.Ssid.Ssid,
  1342. pmlmepriv->cur_network.network.Ssid.SsidLength);
  1343. pframe = rtw_set_fixed_ie(pframe,
  1344. pmlmepriv->cur_network.network.Ssid.SsidLength + 2,
  1345. sub_ie, &pattr->pktlen);
  1346. }
  1347. }
  1348. pattr->last_txcmdsz = pattr->pktlen;
  1349. dump_mgntframe(padapter, pmgntframe);
  1350. return _SUCCESS;
  1351. }
  1352. static u8 *rm_gen_bcn_req_s_elem(_adapter *padapter,
  1353. u8 *pframe, unsigned int *fr_len)
  1354. {
  1355. u8 val8;
  1356. unsigned int my_len = 0;
  1357. u8 bssid[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  1358. val8 = bcn_req_active; /* measurement mode T8-64 */
  1359. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1360. pframe = rtw_set_fixed_ie(pframe, 6, bssid, &my_len);
  1361. /* update length to caller */
  1362. *fr_len += my_len;
  1363. /* optional subelements */
  1364. return pframe;
  1365. }
  1366. static u8 *rm_gen_ch_load_req_s_elem(_adapter *padapter,
  1367. u8 *pframe, unsigned int *fr_len)
  1368. {
  1369. u8 val8;
  1370. unsigned int my_len = 0;
  1371. val8 = 1; /* 1: channel load T8-60 */
  1372. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1373. val8 = 2; /* channel load length = 2 (extensible) */
  1374. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1375. val8 = 0; /* channel load condition : 0 (issue when meas done) T8-61 */
  1376. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1377. val8 = 0; /* channel load reference value : 0 */
  1378. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1379. /* update length to caller */
  1380. *fr_len += my_len;
  1381. return pframe;
  1382. }
  1383. static u8 *rm_gen_noise_histo_req_s_elem(_adapter *padapter,
  1384. u8 *pframe, unsigned int *fr_len)
  1385. {
  1386. u8 val8;
  1387. unsigned int my_len = 0;
  1388. val8 = 1; /* 1: noise histogram T8-62 */
  1389. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1390. val8 = 2; /* noise histogram length = 2 (extensible) */
  1391. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1392. val8 = 0; /* noise histogram condition : 0 (issue when meas done) T8-63 */
  1393. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1394. val8 = 0; /* noise histogram reference value : 0 */
  1395. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1396. /* update length to caller */
  1397. *fr_len += my_len;
  1398. return pframe;
  1399. }
  1400. int issue_radio_meas_req(struct rm_obj *prm)
  1401. {
  1402. u8 val8;
  1403. u8 *pframe;
  1404. u8 *plen;
  1405. u16 val16;
  1406. int my_len, i;
  1407. struct xmit_frame *pmgntframe;
  1408. struct pkt_attrib *pattr;
  1409. _adapter *padapter = prm->psta->padapter;
  1410. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  1411. RTW_INFO("RM: %s - %s\n", __func__, rm_type_req_name(prm->q.m_type));
  1412. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  1413. if (pmgntframe == NULL) {
  1414. RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);
  1415. return _FALSE;
  1416. }
  1417. pattr = &pmgntframe->attrib;
  1418. pframe = build_wlan_hdr(padapter, pmgntframe, prm->psta, WIFI_ACTION);
  1419. pframe = rtw_set_fixed_ie(pframe, 3, &prm->q.category, &pattr->pktlen);
  1420. /* repeat */
  1421. val16 = cpu_to_le16(prm->q.rpt);
  1422. pframe = rtw_set_fixed_ie(pframe, 2,
  1423. (unsigned char *)&(val16), &pattr->pktlen);
  1424. my_len = 0;
  1425. plen = pframe + 1;
  1426. pframe = rtw_set_fixed_ie(pframe, 7, &prm->q.e_id, &my_len);
  1427. /* random interval */
  1428. val16 = 100; /* 100 TU */
  1429. val16 = cpu_to_le16(val16);
  1430. pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
  1431. /* measurement duration */
  1432. val16 = 100;
  1433. val16 = cpu_to_le16(val16);
  1434. pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
  1435. /* optional subelement */
  1436. switch (prm->q.m_type) {
  1437. case bcn_req:
  1438. pframe = rm_gen_bcn_req_s_elem(padapter, pframe, &my_len);
  1439. break;
  1440. case ch_load_req:
  1441. pframe = rm_gen_ch_load_req_s_elem(padapter, pframe, &my_len);
  1442. break;
  1443. case noise_histo_req:
  1444. pframe = rm_gen_noise_histo_req_s_elem(padapter,
  1445. pframe, &my_len);
  1446. break;
  1447. case basic_req:
  1448. default:
  1449. break;
  1450. }
  1451. /* length */
  1452. val8 = (u8)my_len - 2;
  1453. rtw_set_fixed_ie(plen, 1, &val8, &i);
  1454. pattr->pktlen += my_len;
  1455. pattr->last_txcmdsz = pattr->pktlen;
  1456. dump_mgntframe(padapter, pmgntframe);
  1457. return _SUCCESS;
  1458. }
  1459. /* noise histogram */
  1460. static u8 rm_get_anpi(struct rm_obj *prm, struct wlan_network *pnetwork)
  1461. {
  1462. return translate_percentage_to_rcpi(
  1463. pnetwork->network.PhyInfo.SignalStrength);
  1464. }
  1465. int rm_radio_meas_report_cond(struct rm_obj *prm)
  1466. {
  1467. u8 val8;
  1468. int i;
  1469. switch (prm->q.m_type) {
  1470. case ch_load_req:
  1471. val8 = prm->p.ch_load;
  1472. switch (prm->q.opt.clm.rep_cond.cond) {
  1473. case ch_load_cond_immediately:
  1474. return _SUCCESS;
  1475. case ch_load_cond_anpi_equal_greater:
  1476. if (val8 >= prm->q.opt.clm.rep_cond.threshold)
  1477. return _SUCCESS;
  1478. case ch_load_cond_anpi_equal_less:
  1479. if (val8 <= prm->q.opt.clm.rep_cond.threshold)
  1480. return _SUCCESS;
  1481. default:
  1482. break;
  1483. }
  1484. break;
  1485. case noise_histo_req:
  1486. val8 = prm->p.anpi;
  1487. switch (prm->q.opt.nhm.rep_cond.cond) {
  1488. case noise_histo_cond_immediately:
  1489. return _SUCCESS;
  1490. case noise_histo_cond_anpi_equal_greater:
  1491. if (val8 >= prm->q.opt.nhm.rep_cond.threshold)
  1492. return _SUCCESS;
  1493. break;
  1494. case noise_histo_cond_anpi_equal_less:
  1495. if (val8 <= prm->q.opt.nhm.rep_cond.threshold)
  1496. return _SUCCESS;
  1497. break;
  1498. default:
  1499. break;
  1500. }
  1501. break;
  1502. default:
  1503. break;
  1504. }
  1505. return _FAIL;
  1506. }
  1507. int retrieve_radio_meas_result(struct rm_obj *prm)
  1508. {
  1509. HAL_DATA_TYPE *hal_data = GET_HAL_DATA(prm->psta->padapter);
  1510. int i, ch = -1;
  1511. u8 val8;
  1512. ch = rtw_chset_search_ch(adapter_to_chset(prm->psta->padapter),
  1513. prm->q.ch_num);
  1514. if ((ch == -1) || (ch >= MAX_CHANNEL_NUM)) {
  1515. RTW_ERR("RM: get ch(CH:%d) fail\n", prm->q.ch_num);
  1516. ch = 0;
  1517. }
  1518. switch (prm->q.m_type) {
  1519. case ch_load_req:
  1520. #ifdef CONFIG_RTW_ACS
  1521. val8 = hal_data->acs.clm_ratio[ch];
  1522. #else
  1523. val8 = 0;
  1524. #endif
  1525. prm->p.ch_load = val8;
  1526. break;
  1527. case noise_histo_req:
  1528. #ifdef CONFIG_RTW_ACS
  1529. /* ANPI */
  1530. prm->p.anpi = hal_data->acs.nhm_ratio[ch];
  1531. /* IPI 0~10 */
  1532. for (i=0;i<11;i++)
  1533. prm->p.ipi[i] = hal_data->acs.nhm[ch][i];
  1534. #else
  1535. val8 = 0;
  1536. prm->p.anpi = val8;
  1537. for (i=0;i<11;i++)
  1538. prm->p.ipi[i] = val8;
  1539. #endif
  1540. break;
  1541. default:
  1542. break;
  1543. }
  1544. return _SUCCESS;
  1545. }
  1546. int issue_radio_meas_rep(struct rm_obj *prm)
  1547. {
  1548. u8 val8;
  1549. u8 *pframe;
  1550. u8 *plen;
  1551. u16 val16;
  1552. u64 val64;
  1553. unsigned int my_len;
  1554. _adapter *padapter = prm->psta->padapter;
  1555. struct xmit_frame *pmgntframe;
  1556. struct pkt_attrib *pattr;
  1557. struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
  1558. struct sta_info *psta = prm->psta;
  1559. int i;
  1560. RTW_INFO("RM: %s\n", __func__);
  1561. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  1562. if (pmgntframe == NULL) {
  1563. RTW_ERR("RM: ERR %s alloc xmit_frame fail\n",__func__);
  1564. return _FALSE;
  1565. }
  1566. pattr = &pmgntframe->attrib;
  1567. pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);
  1568. pframe = rtw_set_fixed_ie(pframe, 3,
  1569. &prm->p.category, &pattr->pktlen);
  1570. my_len = 0;
  1571. plen = pframe + 1;
  1572. pframe = rtw_set_fixed_ie(pframe, 7, &prm->p.e_id, &my_len);
  1573. /* Actual Meas start time - 8 bytes */
  1574. val64 = cpu_to_le64(prm->meas_start_time);
  1575. pframe = rtw_set_fixed_ie(pframe, 8, (u8 *)&val64, &my_len);
  1576. /* measurement duration */
  1577. val16 = prm->meas_end_time - prm->meas_start_time;
  1578. val16 = cpu_to_le16(val16);
  1579. pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
  1580. /* optional subelement */
  1581. switch (prm->q.m_type) {
  1582. case ch_load_req:
  1583. val8 = prm->p.ch_load;
  1584. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1585. break;
  1586. case noise_histo_req:
  1587. /*
  1588. * AntennaID
  1589. * 0: unknown
  1590. * 255: multiple antenna (Diversity)
  1591. */
  1592. val8 = 0;
  1593. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1594. /* ANPI */
  1595. val8 = prm->p.anpi;
  1596. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1597. /* IPI 0~10 */
  1598. for (i=0;i<11;i++) {
  1599. val8 = prm->p.ipi[i];
  1600. pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
  1601. }
  1602. break;
  1603. default:
  1604. break;
  1605. }
  1606. done:
  1607. /* length */
  1608. val8 = (u8)my_len-2;
  1609. rtw_set_fixed_ie(plen, 1, &val8, &i); /* use variable i to ignore it */
  1610. pattr->pktlen += my_len;
  1611. pattr->last_txcmdsz = pattr->pktlen;
  1612. dump_mgntframe(padapter, pmgntframe);
  1613. return _SUCCESS;
  1614. }
  1615. void rtw_ap_parse_sta_rm_en_cap(_adapter *padapter,
  1616. struct sta_info *psta, struct rtw_ieee802_11_elems *elem)
  1617. {
  1618. if (elem->rm_en_cap) {
  1619. RTW_INFO("assoc.rm_en_cap="RM_CAP_FMT"\n",
  1620. RM_CAP_ARG(elem->rm_en_cap));
  1621. _rtw_memcpy(psta->rm_en_cap,
  1622. (elem->rm_en_cap), elem->rm_en_cap_len);
  1623. }
  1624. }
  1625. void RM_IE_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
  1626. {
  1627. int i;
  1628. _rtw_memcpy(&padapter->rmpriv.rm_en_cap_assoc, pIE->data, pIE->Length);
  1629. RTW_INFO("assoc.rm_en_cap="RM_CAP_FMT"\n", RM_CAP_ARG(pIE->data));
  1630. }
  1631. /* Debug command */
  1632. #if (RM_SUPPORT_IWPRIV_DBG)
  1633. static int hex2num(char c)
  1634. {
  1635. if (c >= '0' && c <= '9')
  1636. return c - '0';
  1637. if (c >= 'a' && c <= 'f')
  1638. return c - 'a' + 10;
  1639. if (c >= 'A' && c <= 'F')
  1640. return c - 'A' + 10;
  1641. return -1;
  1642. }
  1643. int hex2byte(const char *hex)
  1644. {
  1645. int a, b;
  1646. a = hex2num(*hex++);
  1647. if (a < 0)
  1648. return -1;
  1649. b = hex2num(*hex++);
  1650. if (b < 0)
  1651. return -1;
  1652. return (a << 4) | b;
  1653. }
  1654. static char * hwaddr_parse(char *txt, u8 *addr)
  1655. {
  1656. size_t i;
  1657. for (i = 0; i < ETH_ALEN; i++) {
  1658. int a;
  1659. a = hex2byte(txt);
  1660. if (a < 0)
  1661. return NULL;
  1662. txt += 2;
  1663. addr[i] = a;
  1664. if (i < ETH_ALEN - 1 && *txt++ != ':')
  1665. return NULL;
  1666. }
  1667. return txt;
  1668. }
  1669. void rm_dbg_list_sta(_adapter *padapter, char *s)
  1670. {
  1671. int i;
  1672. _irqL irqL;
  1673. struct sta_info *psta;
  1674. struct sta_priv *pstapriv = &padapter->stapriv;
  1675. _list *plist, *phead;
  1676. sprintf(pstr(s), "\n");
  1677. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  1678. for (i = 0; i < NUM_STA; i++) {
  1679. phead = &(pstapriv->sta_hash[i]);
  1680. plist = get_next(phead);
  1681. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
  1682. psta = LIST_CONTAINOR(plist,
  1683. struct sta_info, hash_list);
  1684. plist = get_next(plist);
  1685. sprintf(pstr(s), "=========================================\n");
  1686. sprintf(pstr(s), "mac=" MAC_FMT "\n",
  1687. MAC_ARG(psta->cmn.mac_addr));
  1688. sprintf(pstr(s), "state=0x%x, aid=%d, macid=%d\n",
  1689. psta->state, psta->cmn.aid, psta->cmn.mac_id);
  1690. sprintf(pstr(s), "rm_cap="RM_CAP_FMT"\n",
  1691. RM_CAP_ARG(psta->rm_en_cap));
  1692. }
  1693. }
  1694. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  1695. sprintf(pstr(s), "=========================================\n");
  1696. }
  1697. void rm_dbg_help(_adapter *padapter, char *s)
  1698. {
  1699. int i;
  1700. sprintf(pstr(s), "\n");
  1701. sprintf(pstr(s), "rrm list_sta\n");
  1702. sprintf(pstr(s), "rrm list_meas\n");
  1703. sprintf(pstr(s), "rrm add_meas <aid=1|mac=>,m=<bcn|clm|nhm|nb>,rpt=\n");
  1704. sprintf(pstr(s), "rrm run_meas <aid=1|evid=>\n");
  1705. sprintf(pstr(s), "rrm del_meas\n");
  1706. sprintf(pstr(s), "rrm run_meas rmid=xxxx,ev=xx\n");
  1707. sprintf(pstr(s), "rrm activate\n");
  1708. for (i=0;i<RM_EV_max;i++)
  1709. sprintf(pstr(s), "\t%2d %s\n",i, rm_event_name(i) );
  1710. sprintf(pstr(s), "\n");
  1711. }
  1712. struct sta_info *rm_get_sta(_adapter *padapter, u16 aid, u8* pbssid)
  1713. {
  1714. int i;
  1715. _irqL irqL;
  1716. struct sta_info *psta = NULL;
  1717. struct sta_priv *pstapriv = &padapter->stapriv;
  1718. _list *plist, *phead;
  1719. _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  1720. for (i = 0; i < NUM_STA; i++) {
  1721. phead = &(pstapriv->sta_hash[i]);
  1722. plist = get_next(phead);
  1723. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
  1724. psta = LIST_CONTAINOR(plist,
  1725. struct sta_info, hash_list);
  1726. plist = get_next(plist);
  1727. if (psta->cmn.aid == aid)
  1728. goto done;
  1729. if (pbssid && _rtw_memcmp(psta->cmn.mac_addr,
  1730. pbssid, 6))
  1731. goto done;
  1732. }
  1733. }
  1734. psta = NULL;
  1735. done:
  1736. _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
  1737. return psta;
  1738. }
  1739. static int rm_dbg_modify_meas(_adapter *padapter, char *s)
  1740. {
  1741. struct rm_priv *prmpriv = &padapter->rmpriv;
  1742. struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
  1743. struct rm_obj *prm;
  1744. struct sta_info *psta;
  1745. char *pmac, *ptr, *paid, *prpt, *pnbp, *pclm, *pnhm, *pbcn;
  1746. unsigned val;
  1747. u8 bssid[ETH_ALEN];
  1748. /* example :
  1749. * rrm add_meas <aid=1|mac=>,m=<nb|clm|nhm|bcn>,<rept=>
  1750. * rrm run_meas <aid=1|evid=>
  1751. */
  1752. paid = strstr(s, "aid=");
  1753. pmac = strstr(s, "mac=");
  1754. pbcn = strstr(s, "m=bcn");
  1755. pclm = strstr(s, "m=clm");
  1756. pnhm = strstr(s, "m=nhm");
  1757. pnbp = strstr(s, "m=nb");
  1758. prpt = strstr(s, "rpt=");
  1759. /* set all ',' to NULL (end of line) */
  1760. ptr = s;
  1761. while (ptr) {
  1762. ptr = strchr(ptr, ',');
  1763. if (ptr) {
  1764. *(ptr) = 0x0;
  1765. ptr++;
  1766. }
  1767. }
  1768. prm = (struct rm_obj *)prmpriv->prm_sel;
  1769. prm->q.m_token = 1;
  1770. psta = prm->psta;
  1771. if (paid) { /* find sta_info according to aid */
  1772. paid += 4; /* skip aid= */
  1773. sscanf(paid, "%u", &val); /* aid=x */
  1774. psta = rm_get_sta(padapter, val, NULL);
  1775. } else if (pmac) { /* find sta_info according to bssid */
  1776. pmac += 4; /* skip mac= */
  1777. if (hwaddr_parse(pmac, bssid) == NULL) {
  1778. sprintf(pstr(s), "Err: \nincorrect mac format\n");
  1779. return _FAIL;
  1780. }
  1781. psta = rm_get_sta(padapter, 0xff, bssid);
  1782. }
  1783. if (psta) {
  1784. prm->psta = psta;
  1785. #if 0
  1786. prm->q.diag_token = psta->rm_diag_token++;
  1787. #else
  1788. /* TODO dialog should base on sta_info */
  1789. prm->q.diag_token = pmlmeinfo->dialogToken++;
  1790. #endif
  1791. prm->rmid = psta->cmn.aid << 16
  1792. | prm->q.diag_token << 8
  1793. | RM_MASTER;
  1794. } else
  1795. return _FAIL;
  1796. prm->q.action_code = RM_ACT_RADIO_MEAS_REQ;
  1797. if (pbcn) {
  1798. prm->q.m_type = bcn_req;
  1799. } else if (pnhm) {
  1800. prm->q.m_type = noise_histo_req;
  1801. } else if (pclm) {
  1802. prm->q.m_type = ch_load_req;
  1803. } else if (pnbp) {
  1804. prm->q.action_code = RM_ACT_NB_REP_REQ;
  1805. } else
  1806. return _FAIL;
  1807. if (prpt) {
  1808. prpt += 4; /* skip rpt= */
  1809. sscanf(prpt, "%u", &val);
  1810. prm->q.rpt = (u8)val;
  1811. }
  1812. return _SUCCESS;
  1813. }
  1814. static void rm_dbg_activate_meas(_adapter *padapter, char *s)
  1815. {
  1816. struct rm_priv *prmpriv = &(padapter->rmpriv);
  1817. struct rm_obj *prm;
  1818. if (prmpriv->prm_sel == NULL) {
  1819. sprintf(pstr(s), "\nErr: No inActivate measurement\n");
  1820. return;
  1821. }
  1822. prm = (struct rm_obj *)prmpriv->prm_sel;
  1823. /* verify attributes */
  1824. if (prm->psta == NULL) {
  1825. sprintf(pstr(s), "\nErr: inActivate meas has no psta\n");
  1826. return;
  1827. }
  1828. /* measure current channel */
  1829. prm->q.ch_num = padapter->mlmeextpriv.cur_channel;
  1830. prm->q.op_class = rm_get_oper_class_via_ch(prm->q.ch_num);
  1831. /* enquee rmobj */
  1832. rm_enqueue_rmobj(padapter, prm, _FALSE);
  1833. sprintf(pstr(s), "\nActivate rmid=%x, state=%s, meas_type=%s\n",
  1834. prm->rmid, rm_state_name(prm->state),
  1835. rm_type_req_name(prm->q.m_type));
  1836. sprintf(pstr(s), "aid=%d, mac=" MAC_FMT "\n",
  1837. prm->psta->cmn.aid, MAC_ARG(prm->psta->cmn.mac_addr));
  1838. /* clearn inActivate prm info */
  1839. prmpriv->prm_sel = NULL;
  1840. }
  1841. static void rm_dbg_add_meas(_adapter *padapter, char *s)
  1842. {
  1843. struct rm_priv *prmpriv = &(padapter->rmpriv);
  1844. struct rm_obj *prm;
  1845. char *pact;
  1846. /* example :
  1847. * rrm add_meas <aid=1|mac=>,m=<nb_req|clm_req|nhm_req>
  1848. * rrm run_meas <aid=1|evid=>
  1849. */
  1850. prm = (struct rm_obj *)prmpriv->prm_sel;
  1851. if (prm == NULL)
  1852. prm = rm_alloc_rmobj(padapter);
  1853. if (prm == NULL) {
  1854. sprintf(pstr(s), "\nErr: alloc meas fail\n");
  1855. return;
  1856. }
  1857. prmpriv->prm_sel = prm;
  1858. pact = strstr(s, "act");
  1859. if (rm_dbg_modify_meas(padapter, s) == _FAIL) {
  1860. sprintf(pstr(s), "\nErr: add meas fail\n");
  1861. rm_free_rmobj(prm);
  1862. prmpriv->prm_sel = NULL;
  1863. return;
  1864. }
  1865. prm->q.category = RTW_WLAN_CATEGORY_RADIO_MEAS;
  1866. prm->q.e_id = _MEAS_REQ_IE_; /* 38 */
  1867. if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ)
  1868. sprintf(pstr(s), "\nAdd rmid=%x, meas_type=%s ok\n",
  1869. prm->rmid, rm_type_req_name(prm->q.m_type));
  1870. else if (prm->q.action_code == RM_ACT_NB_REP_REQ)
  1871. sprintf(pstr(s), "\nAdd rmid=%x, meas_type=bcn_req ok\n",
  1872. prm->rmid);
  1873. if (prm->psta)
  1874. sprintf(pstr(s), "mac="MAC_FMT"\n",
  1875. MAC_ARG(prm->psta->cmn.mac_addr));
  1876. if (pact)
  1877. rm_dbg_activate_meas(padapter, pstr(s));
  1878. }
  1879. static void rm_dbg_del_meas(_adapter *padapter, char *s)
  1880. {
  1881. struct rm_priv *prmpriv = &padapter->rmpriv;
  1882. struct rm_obj *prm = (struct rm_obj *)prmpriv->prm_sel;
  1883. if (prm) {
  1884. sprintf(pstr(s), "\ndelete rmid=%x\n",prm->rmid);
  1885. /* free inActivate meas - enqueue yet */
  1886. prmpriv->prm_sel = NULL;
  1887. rtw_mfree(prmpriv->prm_sel, sizeof(struct rm_obj));
  1888. } else
  1889. sprintf(pstr(s), "Err: no inActivate measurement\n");
  1890. }
  1891. static void rm_dbg_run_meas(_adapter *padapter, char *s)
  1892. {
  1893. struct rm_obj *prm;
  1894. char *pevid, *prmid;
  1895. u32 rmid, evid;
  1896. prmid = strstr(s, "rmid="); /* hex */
  1897. pevid = strstr(s, "evid="); /* dec */
  1898. if (prmid && pevid) {
  1899. prmid += 5; /* rmid= */
  1900. sscanf(prmid, "%x", &rmid);
  1901. pevid += 5; /* evid= */
  1902. sscanf(pevid, "%u", &evid);
  1903. } else {
  1904. sprintf(pstr(s), "\nErr: incorrect attribute\n");
  1905. return;
  1906. }
  1907. prm = rm_get_rmobj(padapter, rmid);
  1908. if (!prm) {
  1909. sprintf(pstr(s), "\nErr: measurement not found\n");
  1910. return;
  1911. }
  1912. if (evid >= RM_EV_max) {
  1913. sprintf(pstr(s), "\nErr: wrong event id\n");
  1914. return;
  1915. }
  1916. rm_post_event(padapter, prm->rmid, evid);
  1917. sprintf(pstr(s), "\npost %s to rmid=%x\n",rm_event_name(evid), rmid);
  1918. }
  1919. static void rm_dbg_show_meas(struct rm_obj *prm, char *s)
  1920. {
  1921. struct sta_info *psta;
  1922. psta = prm->psta;
  1923. if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
  1924. sprintf(pstr(s), "\nrmid=%x, meas_type=%s\n",
  1925. prm->rmid, rm_type_req_name(prm->q.m_type));
  1926. } else if (prm->q.action_code == RM_ACT_NB_REP_REQ) {
  1927. sprintf(pstr(s), "\nrmid=%x, action=neighbor_req\n",
  1928. prm->rmid);
  1929. } else
  1930. sprintf(pstr(s), "\nrmid=%x, action=unknown\n",
  1931. prm->rmid);
  1932. if (psta)
  1933. sprintf(pstr(s), "aid=%d, mac="MAC_FMT"\n",
  1934. psta->cmn.aid, MAC_ARG(psta->cmn.mac_addr));
  1935. sprintf(pstr(s), "clock=%d, state=%s, rpt=%u/%u\n",
  1936. (int)ATOMIC_READ(&prm->pclock->counter),
  1937. rm_state_name(prm->state), prm->p.rpt, prm->q.rpt);
  1938. }
  1939. static void rm_dbg_list_meas(_adapter *padapter, char *s)
  1940. {
  1941. int meas_amount;
  1942. _irqL irqL;
  1943. struct rm_obj *prm;
  1944. struct sta_info *psta;
  1945. struct rm_priv *prmpriv = &padapter->rmpriv;
  1946. _queue *queue = &prmpriv->rm_queue;
  1947. _list *plist, *phead;
  1948. sprintf(pstr(s), "\n");
  1949. _enter_critical(&queue->lock, &irqL);
  1950. phead = get_list_head(queue);
  1951. plist = get_next(phead);
  1952. meas_amount = 0;
  1953. while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
  1954. prm = LIST_CONTAINOR(plist, struct rm_obj, list);
  1955. meas_amount++;
  1956. plist = get_next(plist);
  1957. psta = prm->psta;
  1958. sprintf(pstr(s), "=========================================\n");
  1959. rm_dbg_show_meas(prm, s);
  1960. }
  1961. _exit_critical(&queue->lock, &irqL);
  1962. sprintf(pstr(s), "=========================================\n");
  1963. if (meas_amount==0) {
  1964. sprintf(pstr(s), "No Activate measurement\n");
  1965. sprintf(pstr(s), "=========================================\n");
  1966. }
  1967. if (prmpriv->prm_sel == NULL)
  1968. sprintf(pstr(s), "\nNo inActivate measurement\n");
  1969. else {
  1970. sprintf(pstr(s), "\ninActivate measurement\n");
  1971. rm_dbg_show_meas((struct rm_obj *)prmpriv->prm_sel, s);
  1972. }
  1973. }
  1974. #endif /* RM_SUPPORT_IWPRIV_DBG */
  1975. void rm_dbg_cmd(_adapter *padapter, char *s)
  1976. {
  1977. unsigned val;
  1978. char *paid;
  1979. struct sta_info *psta=NULL;
  1980. #if (RM_SUPPORT_IWPRIV_DBG)
  1981. if (_rtw_memcmp(s, "help", 4)) {
  1982. rm_dbg_help(padapter, s);
  1983. } else if (_rtw_memcmp(s, "list_sta", 8)) {
  1984. rm_dbg_list_sta(padapter, s);
  1985. } else if (_rtw_memcmp(s, "list_meas", 9)) {
  1986. rm_dbg_list_meas(padapter, s);
  1987. } else if (_rtw_memcmp(s, "add_meas", 8)) {
  1988. rm_dbg_add_meas(padapter, s);
  1989. } else if (_rtw_memcmp(s, "del_meas", 8)) {
  1990. rm_dbg_del_meas(padapter, s);
  1991. } else if (_rtw_memcmp(s, "activate", 8)) {
  1992. rm_dbg_activate_meas(padapter, s);
  1993. } else if (_rtw_memcmp(s, "run_meas", 8)) {
  1994. rm_dbg_run_meas(padapter, s);
  1995. } else if (_rtw_memcmp(s, "nb", 2)) {
  1996. paid = strstr(s, "aid=");
  1997. if (paid) { /* find sta_info according to aid */
  1998. paid += 4; /* skip aid= */
  1999. sscanf(paid, "%u", &val); /* aid=x */
  2000. psta = rm_get_sta(padapter, val, NULL);
  2001. if (psta)
  2002. rm_add_nb_req(padapter, psta);
  2003. }
  2004. }
  2005. #else
  2006. sprintf(pstr(s), "\n");
  2007. sprintf(pstr(s), "rrm debug command was disabled\n");
  2008. #endif
  2009. }
  2010. #endif /* CONFIG_RTW_80211K */