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