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