• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
cnt_rm_report_ies(struct rm_obj * prm,u8 eid,u8 * buf,u32 buf_len)799 static u8 cnt_rm_report_ies(struct rm_obj *prm, u8 eid, u8 *buf, u32 buf_len)
800 {
801 	u8 *pos = buf;
802 	u8 id, len, cnt = 0;
803 
804 	while (pos - buf + 1 < buf_len) {
805 		id = *pos;
806 		len = *(pos + 1);
807 
808 		if (id == eid)
809 			cnt++;
810 			/*indicate_beacon_report(prm->psta->cmn.mac_addr,*/
811 			/*1, 2 + len, pos);*/
812 
813 		pos += (2 + len);
814 	}
815 	return cnt;
816 }
817 
818 /* receive measurement report */
rm_recv_radio_mens_rep(_adapter * padapter,union recv_frame * precv_frame,struct sta_info * psta)819 int rm_recv_radio_mens_rep(_adapter *padapter,
820 	union recv_frame *precv_frame, struct sta_info *psta)
821 {
822 	u32 len;
823 	struct rm_obj *prm;
824 	u32 rmid;
825 	u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +
826 		sizeof(struct rtw_ieee80211_hdr_3addr));
827 	u8 *pmeas_body = &pdiag_body[3];
828 	u8 bcn_rpt_cnt;
829 
830 
831 	rmid = psta->cmn.aid << 16
832 		| pdiag_body[2] << 8
833 		| RM_MASTER;
834 
835 	prm = rm_get_rmobj(padapter, rmid);
836 	if (prm == NULL) {
837 		/* not belong to us, report to upper */
838 		rtw_cfg80211_rx_rrm_action(psta->padapter, precv_frame);
839 		return _TRUE;
840 	}
841 
842 	prm->p.action_code = pdiag_body[1];
843 	prm->p.diag_token = pdiag_body[2];
844 
845 	/* Figure 8-140 Measuremnt Report format */
846 	prm->p.e_id = pmeas_body[0];
847 	prm->p.m_token = pmeas_body[2];
848 	prm->p.m_mode = pmeas_body[3];
849 	prm->p.m_type = pmeas_body[4];
850 
851 	RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,
852 		MAC_ARG(prm->psta->cmn.mac_addr));
853 
854 #if (RM_MORE_DBG_MSG)
855 	RTW_INFO("RM: element_id = %d\n", prm->p.e_id);
856 	RTW_INFO("RM: length = %d\n", (int)pmeas_body[1]);
857 	RTW_INFO("RM: meas_token = %d\n", prm->p.m_token);
858 	RTW_INFO("RM: meas_mode = %d\n", prm->p.m_mode);
859 	RTW_INFO("RM: meas_type = %d\n", prm->p.m_type);
860 #endif
861 	if (prm->p.e_id != _MEAS_RSP_IE_) /* 39 */
862 		return _FALSE;
863 
864 	RTW_INFO("RM: recv %s\n", rm_type_rep_name(prm->p.m_type));
865 	rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);
866 
867 	/* report to upper via ioctl */
868 	if ((prm->from_ioctl == true) &&
869 		prm->q.m_type == bcn_req) {
870 		len = precv_frame->u.hdr.len -
871 				sizeof(struct rtw_ieee80211_hdr_3addr) -
872 				3; /* Category + Action code + token */
873 
874 		bcn_rpt_cnt = cnt_rm_report_ies(prm, _MEAS_RSP_IE_,
875 						pmeas_body, len);
876 		if (bcn_rpt_cnt > 0)
877 			indicate_beacon_report(prm->psta->cmn.mac_addr,
878 					       bcn_rpt_cnt, len, pmeas_body);
879 	}
880 	return _TRUE;
881 }
882 
883 /* receive link measurement request */
rm_recv_link_mens_req(_adapter * padapter,union recv_frame * precv_frame,struct sta_info * psta)884 int rm_recv_link_mens_req(_adapter *padapter,
885 	union recv_frame *precv_frame, struct sta_info *psta)
886 {
887 	struct rm_obj *prm;
888 	struct rm_priv *prmpriv = &padapter->rmpriv;
889 	u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +
890 		sizeof(struct rtw_ieee80211_hdr_3addr));
891 	u8 *pmeas_body = &pdiag_body[3];
892 	u8 rmid, update = 0;
893 	int i;
894 
895 
896 	prm = rm_alloc_rmobj(padapter);
897 
898 	if (prm == NULL) {
899 		RTW_ERR("RM: unable to alloc rm obj for requeset\n");
900 		return _FALSE;
901 	}
902 
903 	prm->psta = psta;
904 	prm->q.action_code = pdiag_body[1];
905 	prm->q.diag_token = pdiag_body[2];
906 
907 	prm->q.tx_pwr_used = pmeas_body[0];
908 	prm->q.tx_pwr_max = pmeas_body[1];
909 	prm->q.rx_pwr = precv_frame->u.hdr.attrib.phy_info.rx_power;
910 	prm->q.rx_rate = hw_rate_to_m_rate(precv_frame->u.hdr.attrib.data_rate);
911 	prm->q.rx_bw = precv_frame->u.hdr.attrib.bw;
912 	prm->q.rx_rsni = rm_get_frame_rsni(prm, precv_frame);
913 	prm->rmid = rm_gen_rmid(padapter, prm, RM_SLAVE);
914 
915 	RTW_INFO("RM: rmid=%x, bssid" MAC_FMT " rx_pwr=%ddBm, rate=%s\n",
916 		prm->rmid, MAC_ARG(prm->psta->cmn.mac_addr), prm->q.rx_pwr,
917 		MGN_RATE_STR(prm->q.rx_rate));
918 
919 #if (RM_MORE_DBG_MSG)
920 	RTW_INFO("RM: tx_pwr_used =%d dBm\n", prm->q.tx_pwr_used);
921 	RTW_INFO("RM: tx_pwr_max  =%d dBm\n", prm->q.tx_pwr_max);
922 #endif
923 
924 	if (!update)
925 		rm_enqueue_rmobj(padapter, prm, _FALSE);
926 
927 	return _SUCCESS;
928 }
929 
930 /* receive link measurement report */
rm_recv_link_mens_rep(_adapter * padapter,union recv_frame * precv_frame,struct sta_info * psta)931 int rm_recv_link_mens_rep(_adapter *padapter,
932 	union recv_frame *precv_frame, struct sta_info *psta)
933 {
934 	int ret = _FALSE;
935 	struct rm_obj *prm;
936 	u32 rmid;
937 	u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +
938 		sizeof(struct rtw_ieee80211_hdr_3addr));
939 	u8 *pmeas_body = pdiag_body + 3;
940 	s8 val;
941 
942 
943 	rmid = psta->cmn.aid << 16
944 		| pdiag_body[2] << 8
945 		| RM_MASTER;
946 
947 	prm = rm_get_rmobj(padapter, rmid);
948 	if (prm == NULL) {
949 		/* not belong to us, report to upper */
950 		rtw_cfg80211_rx_rrm_action(psta->padapter, precv_frame);
951 		return _TRUE;
952 	}
953 
954 	RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,
955 		MAC_ARG(prm->psta->cmn.mac_addr));
956 
957 	prm->p.action_code = pdiag_body[1];
958 	prm->p.diag_token = pdiag_body[2];
959 
960 #if (RM_MORE_DBG_MSG)
961 	RTW_INFO("RM: action_code = %d\n", prm->p.action_code);
962 	RTW_INFO("RM: diag_token  = %d\n", prm->p.diag_token);
963 	RTW_INFO("RM: xmit_power  = %d dBm\n", pmeas_body[2]);
964 	RTW_INFO("RM: link_margin = %d dBm\n", pmeas_body[3]);
965 	RTW_INFO("RM: xmit_ant    = %d\n", pmeas_body[4]);
966 	RTW_INFO("RM: recv_ant    = %d\n", pmeas_body[5]);
967 	RTW_INFO("RM: RCPI        = %d\n", pmeas_body[6]);
968 	RTW_INFO("RM: RSNI        = %d\n", pmeas_body[7]);
969 #endif
970 	RTW_INFO("RM: recv link meas report ...\n");
971 	ret = rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);
972 
973 	return ret;
974 }
975 
976 
rm_radio_mens_nb_rep(_adapter * padapter,union recv_frame * precv_frame,struct sta_info * psta)977 int rm_radio_mens_nb_rep(_adapter *padapter,
978 	union recv_frame *precv_frame, struct sta_info *psta)
979 {
980 	u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +
981 		sizeof(struct rtw_ieee80211_hdr_3addr));
982 	u8 *pmeas_body = &pdiag_body[3];
983 	u32 len = precv_frame->u.hdr.len;
984 	u32 rmid;
985 	struct rm_obj *prm;
986 
987 
988 	rmid = psta->cmn.aid << 16
989 		| pdiag_body[2] << 8
990 		| RM_MASTER;
991 
992 	prm = rm_get_rmobj(padapter, rmid);
993 
994 	if (prm == NULL) {
995 		/* not belong to us, report to upper */
996 		rtw_cfg80211_rx_rrm_action(psta->padapter, precv_frame);
997 		return _TRUE;
998 	}
999 
1000 	prm->p.action_code = pdiag_body[1];
1001 	prm->p.diag_token = pdiag_body[2];
1002 	prm->p.e_id = pmeas_body[0];
1003 
1004 	RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,
1005 		MAC_ARG(prm->psta->cmn.mac_addr));
1006 
1007 #if (RM_MORE_DBG_MSG)
1008 	RTW_INFO("RM: element_id = %d\n", prm->p.e_id);
1009 	RTW_INFO("RM: length = %d\n", (int)pmeas_body[1]);
1010 #endif
1011 	rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);
1012 
1013 #ifdef CONFIG_LAYER2_ROAMING
1014 	if (rtw_wnm_btm_candidates_survey(padapter
1015 			,(pdiag_body + 3)
1016 			,(len - sizeof(struct rtw_ieee80211_hdr_3addr))
1017 			,_FALSE) == _FAIL)
1018 		return _FALSE;
1019 #endif
1020 	rtw_cfg80211_rx_rrm_action(padapter, precv_frame);
1021 
1022 	return _TRUE;
1023 }
1024 
rm_on_action(_adapter * padapter,union recv_frame * precv_frame)1025 unsigned int rm_on_action(_adapter *padapter, union recv_frame *precv_frame)
1026 {
1027 	u32 ret = _FAIL;
1028 	u8 *pframe = NULL;
1029 	u8 *pframe_body = NULL;
1030 	u8 action_code = 0;
1031 	u8 diag_token = 0;
1032 	struct rtw_ieee80211_hdr_3addr *whdr;
1033 	struct sta_info *psta;
1034 
1035 
1036 	pframe = precv_frame->u.hdr.rx_data;
1037 
1038 	/* check RA matches or not */
1039 	if (!_rtw_memcmp(adapter_mac_addr(padapter),
1040 		GetAddr1Ptr(pframe), ETH_ALEN))
1041 		goto exit;
1042 
1043 	whdr = (struct rtw_ieee80211_hdr_3addr *)pframe;
1044 	RTW_INFO("RM: %s bssid = " MAC_FMT "\n",
1045 		__func__, MAC_ARG(whdr->addr2));
1046 
1047 	psta = rtw_get_stainfo(&padapter->stapriv, whdr->addr2);
1048 
1049         if (!psta) {
1050 		RTW_ERR("RM: psta not found\n");
1051                 goto exit;
1052         }
1053 
1054 	pframe_body = (unsigned char *)(pframe +
1055 		sizeof(struct rtw_ieee80211_hdr_3addr));
1056 
1057 	/* Figure 8-438 radio measurement request frame Action field format */
1058 	/* Category = pframe_body[0] = 5 (Radio Measurement) */
1059 	action_code = pframe_body[1];
1060 	diag_token = pframe_body[2];
1061 
1062 #if (RM_MORE_DBG_MSG)
1063 	RTW_INFO("RM: %s radio_action=%x, diag_token=%x\n", __func__,
1064 		action_code, diag_token);
1065 #endif
1066 
1067 	switch (action_code) {
1068 
1069 	case RM_ACT_RADIO_MEAS_REQ:
1070 		RTW_INFO("RM: RM_ACT_RADIO_MEAS_REQ\n");
1071 		ret = rm_recv_radio_mens_req(padapter, precv_frame, psta);
1072 		break;
1073 
1074 	case RM_ACT_RADIO_MEAS_REP:
1075 		RTW_INFO("RM: RM_ACT_RADIO_MEAS_REP\n");
1076 		ret = rm_recv_radio_mens_rep(padapter, precv_frame, psta);
1077 		break;
1078 
1079 	case RM_ACT_LINK_MEAS_REQ:
1080 		RTW_INFO("RM: RM_ACT_LINK_MEAS_REQ\n");
1081 		ret = rm_recv_link_mens_req(padapter, precv_frame, psta);
1082 		break;
1083 
1084 	case RM_ACT_LINK_MEAS_REP:
1085 		RTW_INFO("RM: RM_ACT_LINK_MEAS_REP\n");
1086 		ret = rm_recv_link_mens_rep(padapter, precv_frame, psta);
1087 		break;
1088 
1089 	case RM_ACT_NB_REP_REQ:
1090 		RTW_INFO("RM: RM_ACT_NB_REP_REQ\n");
1091 		break;
1092 
1093 	case RM_ACT_NB_REP_RESP:
1094 		RTW_INFO("RM: RM_ACT_NB_REP_RESP\n");
1095 		ret = rm_radio_mens_nb_rep(padapter, precv_frame, psta);
1096 		break;
1097 
1098 	default:
1099 		/* TODO reply incabable */
1100 		RTW_ERR("RM: unknown specturm management action %2x\n",
1101 			action_code);
1102 		break;
1103 	}
1104 exit:
1105 	return ret;
1106 }
1107 
rm_gen_bcn_detail_elem(_adapter * padapter,u8 * pframe,struct rm_obj * prm,struct wlan_network * pnetwork,unsigned int * fr_len)1108 static u8 *rm_gen_bcn_detail_elem(_adapter *padapter, u8 *pframe,
1109 	struct rm_obj *prm, struct wlan_network *pnetwork,
1110 	unsigned int *fr_len)
1111 {
1112 	WLAN_BSSID_EX *pbss = &pnetwork->network;
1113 	unsigned int my_len;
1114 	int j, k, len;
1115 	u8 *plen;
1116 	u8 *ptr;
1117 	u8 val8, eid;
1118 
1119 
1120 	my_len = 0;
1121 	/* Reporting Detail values
1122 	 * 0: No fixed length fields or elements
1123 	 * 1: All fixed length fields and any requested elements
1124 	 *    in the Request info element if present
1125 	 * 2: All fixed length fields and elements
1126 	 * 3-255: Reserved
1127 	 */
1128 
1129 	/* report_detail = 0 */
1130 	if (prm->q.opt.bcn.rep_detail == 0
1131 		|| prm->q.opt.bcn.rep_detail > 2) {
1132 		return pframe;
1133 	}
1134 
1135 	/* ID */
1136 	val8 = 1; /* 1:reported frame body */
1137 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1138 
1139 	plen = pframe;
1140 	val8 = 0;
1141 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1142 
1143 	/* report_detail = 2 */
1144 	if (prm->q.opt.bcn.rep_detail == 2) {
1145 		pframe = rtw_set_fixed_ie(pframe, pbss->IELength - 4,
1146 			pbss->IEs, &my_len); /* -4 remove FCS */
1147 		goto done;
1148 	}
1149 
1150 	/* report_detail = 1 */
1151 	/* all fixed lenght fields */
1152 	pframe = rtw_set_fixed_ie(pframe,
1153 		_FIXED_IE_LENGTH_, pbss->IEs, &my_len);
1154 
1155 	for (j = 0; j < prm->q.opt.bcn.opt_id_num; j++) {
1156 		switch (prm->q.opt.bcn.opt_id[j]) {
1157 		case bcn_req_ssid:
1158 			/* SSID */
1159 #if (RM_MORE_DBG_MSG)
1160 			RTW_INFO("RM: bcn_req_ssid\n");
1161 #endif
1162 			pframe = rtw_set_ie(pframe, _SSID_IE_,
1163 				pbss->Ssid.SsidLength,
1164 				pbss->Ssid.Ssid, &my_len);
1165 			break;
1166 		case bcn_req_req:
1167 			if (prm->q.opt.bcn.req_start == NULL)
1168 				break;
1169 #if (RM_MORE_DBG_MSG)
1170 			RTW_INFO("RM: bcn_req_req");
1171 #endif
1172 			for (k=0; k<prm->q.opt.bcn.req_len; k++) {
1173 				eid = prm->q.opt.bcn.req_start[k];
1174 
1175 				val8 = pbss->IELength - _FIXED_IE_LENGTH_;
1176 				ptr = rtw_get_ie(pbss->IEs + _FIXED_IE_LENGTH_,
1177 					eid, &len, val8);
1178 
1179 				if (!ptr)
1180 					continue;
1181 #if (RM_MORE_DBG_MSG)
1182 				switch (eid) {
1183 				case EID_SsId:
1184 					RTW_INFO("RM: EID_SSID\n");
1185 					break;
1186 				case EID_QBSSLoad:
1187 					RTW_INFO("RM: EID_QBSSLoad\n");
1188 					break;
1189 				case EID_HTCapability:
1190 					RTW_INFO("RM: EID_HTCapability\n");
1191 					break;
1192 				case _MDIE_:
1193 					RTW_INFO("RM: EID_MobilityDomain\n");
1194 					break;
1195 				case EID_Vendor:
1196 					RTW_INFO("RM: EID_Vendor\n");
1197 					break;
1198 				default:
1199 					RTW_INFO("RM: EID %d todo\n",eid);
1200 					break;
1201 				}
1202 #endif
1203 				pframe = rtw_set_ie(pframe, eid,
1204 					len, ptr+2, &my_len);
1205 			} /* for() */
1206 			break;
1207 		case bcn_req_rep_detail:
1208 			RTW_INFO("RM: bcn_req_rep_detail\n");
1209 			break;
1210 		case bcn_req_ap_ch_rep:
1211 			RTW_INFO("RM: bcn_req_ap_ch_rep\n");
1212 			break;
1213 		default:
1214 			RTW_INFO("RM: OPT %d TODO\n",prm->q.opt.bcn.opt_id[j]);
1215 			break;
1216 		}
1217 	}
1218 done:
1219 	/*
1220 	 * update my length
1221 	 * content length does NOT include ID and LEN
1222 	 */
1223 	val8 = my_len - 2;
1224 	rtw_set_fixed_ie(plen, 1, &val8, &j);
1225 
1226 	/* update length to caller */
1227 	*fr_len += my_len;
1228 
1229 	return pframe;
1230 }
1231 
rm_bcn_req_cond_mach(struct rm_obj * prm,struct wlan_network * pnetwork)1232 u8 rm_bcn_req_cond_mach(struct rm_obj *prm, struct wlan_network *pnetwork)
1233 {
1234 	u8 val8;
1235 
1236 
1237 	switch(prm->q.opt.bcn.rep_cond.cond) {
1238 	case bcn_rep_cond_immediately:
1239 		return _SUCCESS;
1240 	case bcn_req_cond_rcpi_greater:
1241 		val8 = rm_get_bcn_rcpi(prm, pnetwork);
1242 		if (val8 > prm->q.opt.bcn.rep_cond.threshold)
1243 			return _SUCCESS;
1244 		break;
1245 	case bcn_req_cond_rcpi_less:
1246 		val8 = rm_get_bcn_rcpi(prm, pnetwork);
1247 		if (val8 < prm->q.opt.bcn.rep_cond.threshold)
1248 			return _SUCCESS;
1249 		break;
1250 	case bcn_req_cond_rsni_greater:
1251 		val8 = rm_get_bcn_rsni(prm, pnetwork);
1252 		if (val8 != 255 && val8 > prm->q.opt.bcn.rep_cond.threshold)
1253 			return _SUCCESS;
1254 		break;
1255 	case bcn_req_cond_rsni_less:
1256 		val8 = rm_get_bcn_rsni(prm, pnetwork);
1257 		if (val8 != 255 && val8 < prm->q.opt.bcn.rep_cond.threshold)
1258 			return _SUCCESS;
1259 		break;
1260 	default:
1261 		RTW_ERR("RM: bcn_req cond %u not support\n",
1262 			prm->q.opt.bcn.rep_cond.cond);
1263 		break;
1264 	}
1265 	return _FALSE;
1266 }
1267 
rm_gen_bcn_rep_ie(struct rm_obj * prm,u8 * pframe,struct wlan_network * pnetwork,unsigned int * fr_len)1268 static u8 *rm_gen_bcn_rep_ie (struct rm_obj *prm,
1269 	u8 *pframe, struct wlan_network *pnetwork, unsigned int *fr_len)
1270 {
1271 	int snr, i;
1272 	u8 val8, *plen;
1273 	u16 val16;
1274 	u32 val32;
1275 	u64 val64;
1276 	unsigned int my_len;
1277 	_adapter *padapter = prm->psta->padapter;
1278 
1279 
1280 	my_len = 0;
1281 	plen = pframe + 1;
1282 	pframe = rtw_set_fixed_ie(pframe, 7, &prm->p.e_id, &my_len);
1283 
1284 	/* Actual Measurement StartTime */
1285 	val64 = cpu_to_le64(prm->meas_start_time);
1286 	pframe = rtw_set_fixed_ie(pframe, 8, (u8 *)&val64, &my_len);
1287 
1288 	/* Measurement Duration */
1289 	val16 = prm->meas_end_time - prm->meas_start_time;
1290 	val16 = cpu_to_le16(val16);
1291 	pframe = rtw_set_fixed_ie(pframe, 2, (u8*)&val16, &my_len);
1292 
1293 	/* TODO
1294 	* ReportedFrameInformation:
1295 	* 0 :beacon or probe rsp
1296 	* 1 :pilot frame
1297 	*/
1298 	val8 = 0; /* report frame info */
1299 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1300 
1301 	/* RCPI */
1302 	val8 = rm_get_bcn_rcpi(prm, pnetwork);
1303 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1304 
1305 	/* RSNI */
1306 	val8 = rm_get_bcn_rsni(prm, pnetwork);
1307 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1308 
1309 	/* BSSID */
1310 	pframe = rtw_set_fixed_ie(pframe, 6,
1311 		(u8 *)&pnetwork->network.MacAddress, &my_len);
1312 
1313 	/*
1314 	 * AntennaID
1315 	 * 0: unknown
1316 	 * 255: multiple antenna (Diversity)
1317 	 */
1318 	val8 = 0;
1319 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1320 
1321 	/* ParentTSF */
1322 	val32 = pnetwork->network.PhyInfo.free_cnt;
1323 	if (prm->free_run_counter_valid)
1324 		val32 += prm->meas_start_time;
1325 
1326 	pframe = rtw_set_fixed_ie(pframe, 4, (u8 *)&val32, &my_len);
1327 
1328 	/* Generate Beacon detail */
1329 	pframe = rm_gen_bcn_detail_elem(padapter, pframe,
1330 		prm, pnetwork, &my_len);
1331 	/*
1332 	* update my length
1333 	* content length does NOT include ID and LEN
1334 	*/
1335 	val8 = my_len - 2;
1336 	rtw_set_fixed_ie(plen, 1, &val8, &i);
1337 
1338 	/* update length to caller */
1339 	*fr_len += my_len;
1340 
1341 	return pframe;
1342 }
1343 
1344 #if 0 /* check MBO logo */
1345 static int rm_match_sub_elem(_adapter *padapter,
1346 	struct rm_obj *prm, struct wlan_network *pnetwork)
1347 {
1348 	WLAN_BSSID_EX *pbss = &pnetwork->network;
1349 	unsigned int my_len;
1350 	int j, k, len;
1351 	u8 *plen;
1352 	u8 *ptr;
1353 	u8 val8, eid;
1354 
1355 
1356 	my_len = 0;
1357 	/* Reporting Detail values
1358 	 * 0: No fixed length fields or elements
1359 	 * 1: All fixed length fields and any requested elements
1360 	 *    in the Request info element if present
1361 	 * 2: All fixed length fields and elements
1362 	 * 3-255: Reserved
1363 	 */
1364 
1365 	/* report_detail != 1  */
1366 	if (prm->q.opt.bcn.rep_detail != 1)
1367 		return _TRUE;
1368 
1369 	/* report_detail = 1 */
1370 
1371 	for (j = 0; j < prm->q.opt.bcn.opt_id_num; j++) {
1372 		switch (prm->q.opt.bcn.opt_id[j]) {
1373 		case bcn_req_ssid:
1374 			/* SSID */
1375 #if (RM_MORE_DBG_MSG)
1376 			RTW_INFO("RM: bcn_req_ssid\n");
1377 #endif
1378 			if (pbss->Ssid.SsidLength == 0)
1379 				return _FALSE;
1380 			break;
1381 		case bcn_req_req:
1382 			if (prm->q.opt.bcn.req_start == NULL)
1383 				break;
1384 #if (RM_MORE_DBG_MSG)
1385 			RTW_INFO("RM: bcn_req_req");
1386 #endif
1387 			for (k=0; k<prm->q.opt.bcn.req_len; k++) {
1388 				eid = prm->q.opt.bcn.req_start[k];
1389 
1390 				val8 = pbss->IELength - _FIXED_IE_LENGTH_;
1391 				ptr = rtw_get_ie(pbss->IEs + _FIXED_IE_LENGTH_,
1392 					eid, &len, val8);
1393 
1394 #if (RM_MORE_DBG_MSG)
1395 				switch (eid) {
1396 				case EID_SsId:
1397 					RTW_INFO("RM: EID_SSID\n");
1398 					break;
1399 				case EID_QBSSLoad:
1400 					RTW_INFO("RM: EID_QBSSLoad\n");
1401 					break;
1402 				case EID_HTCapability:
1403 					RTW_INFO("RM: EID_HTCapability\n");
1404 					break;
1405 				case _MDIE_:
1406 					RTW_INFO("RM: EID_MobilityDomain\n");
1407 					break;
1408 				case EID_Vendor:
1409 					RTW_INFO("RM: EID_Vendor\n");
1410 					break;
1411 				default:
1412 					RTW_INFO("RM: EID %d todo\n",eid);
1413 					break;
1414 				}
1415 #endif
1416 				if (!ptr) {
1417 					RTW_INFO("RM: EID %d not found\n",eid);
1418 					return _FALSE;
1419 				}
1420 			} /* for() */
1421 			break;
1422 		case bcn_req_rep_detail:
1423 			RTW_INFO("RM: bcn_req_rep_detail\n");
1424 			break;
1425 		case bcn_req_ap_ch_rep:
1426 			RTW_INFO("RM: bcn_req_ap_ch_rep\n");
1427 			break;
1428 		default:
1429 			RTW_INFO("RM: OPT %d TODO\n",prm->q.opt.bcn.opt_id[j]);
1430 			break;
1431 		}
1432 	}
1433 	return _TRUE;
1434 }
1435 #endif
1436 
retrieve_scan_result(struct rm_obj * prm)1437 static int retrieve_scan_result(struct rm_obj *prm)
1438 {
1439 	_irqL irqL;
1440 	_list *plist, *phead;
1441 	_queue *queue;
1442 	_adapter *padapter = prm->psta->padapter;
1443 	struct rtw_ieee80211_channel *pch_set;
1444 	struct wlan_network *pnetwork = NULL;
1445 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1446 	int i;
1447 	PWLAN_BSSID_EX pbss;
1448 	unsigned int matched_network;
1449 	int len, my_len;
1450 	u8 buf_idx, *pbuf = NULL, *tmp_buf = NULL;
1451 
1452 
1453 	tmp_buf = rtw_malloc(MAX_XMIT_EXTBUF_SZ);
1454 	if (tmp_buf == NULL)
1455 		return 0;
1456 
1457 	my_len = 0;
1458 	buf_idx = 0;
1459 	matched_network = 0;
1460 	queue = &(pmlmepriv->scanned_queue);
1461 
1462 	_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
1463 
1464 	phead = get_list_head(queue);
1465 	plist = get_next(phead);
1466 
1467 	/* get requested measurement channel set */
1468 	pch_set = prm->q.ch_set;
1469 
1470 	/* search scan queue to find requested SSID */
1471 	while (1) {
1472 
1473 		if (rtw_end_of_queue_search(phead, plist) == _TRUE)
1474 			break;
1475 
1476 		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1477 		pbss = &pnetwork->network;
1478 
1479 #if 0
1480 		RTW_INFO("RM: ooo ch %u ssid %s bssid "MAC_FMT"\n",
1481 			pbss->Configuration.DSConfig, pbss->Ssid.Ssid,
1482 			MAC_ARG(pbss->MacAddress));
1483 		/*
1484 		* report network if requested channel set contains
1485 		* the channel matchs selected network
1486 		*/
1487 		if (rtw_chset_search_ch(adapter_to_chset(padapter),
1488 			pbss->Configuration.DSConfig) < 0) /* not match */
1489 			goto next;
1490 
1491 		if (rtw_mlme_band_check(padapter, pbss->Configuration.DSConfig)
1492 			== _FALSE)
1493 			goto next;
1494 #endif
1495 		if (rtw_validate_ssid(&(pbss->Ssid)) == _FALSE)
1496 			goto next;
1497 
1498 		/* match bssid */
1499 		if (is_wildcard_bssid(prm->q.bssid) == FALSE)
1500 			if (_rtw_memcmp(prm->q.bssid,
1501 				pbss->MacAddress, 6) == _FALSE)
1502 				//continue;
1503 				goto next;
1504 		/*
1505 		 * default wildcard SSID. wildcard SSID:
1506 		 * A SSID value (null) used to represent all SSIDs
1507 		 */
1508 
1509 		/* match ssid */
1510 		if ((prm->q.opt.bcn.ssid.SsidLength > 0) &&
1511 			_rtw_memcmp(prm->q.opt.bcn.ssid.Ssid,
1512 			pbss->Ssid.Ssid,
1513 			prm->q.opt.bcn.ssid.SsidLength) == _FALSE)
1514 			goto next;
1515 
1516 		/* go through measurement requested channels */
1517 		for (i = 0; i < prm->q.ch_set_ch_amount; i++) {
1518 			if ((pch_set[i].hw_value) ==
1519 				(pbss->Configuration.DSConfig)) /* match ch */
1520 				break;
1521 		}
1522 		if (i >= prm->q.ch_set_ch_amount) /* channel mismatch */
1523 			goto next;
1524 
1525 		/* match condition */
1526 		if (rm_bcn_req_cond_mach(prm, pnetwork) == _FALSE) {
1527 			RTW_INFO("RM: condition mismatch ch %u ssid %s bssid "MAC_FMT"\n",
1528 				pbss->Configuration.DSConfig, pbss->Ssid.Ssid,
1529 				MAC_ARG(pbss->MacAddress));
1530 			RTW_INFO("RM: condition %u:%u\n",
1531 				prm->q.opt.bcn.rep_cond.cond,
1532 				prm->q.opt.bcn.rep_cond.threshold);
1533 			goto next;
1534 			//continue;
1535 		}
1536 #if 0 /* check MBO logo */
1537 		/* match subelement */
1538 		if (rm_match_sub_elem(padapter, prm, pnetwork) == _FALSE)
1539 			goto next;
1540 #endif
1541 		/* Found a matched SSID */
1542 		matched_network++;
1543 
1544 		RTW_INFO("RM: ch %u Found %s bssid "MAC_FMT"\n",
1545 			pbss->Configuration.DSConfig, pbss->Ssid.Ssid,
1546 			MAC_ARG(pbss->MacAddress));
1547 
1548 		len = 0;
1549 		_rtw_memset(tmp_buf, 0, MAX_XMIT_EXTBUF_SZ);
1550 		rm_gen_bcn_rep_ie(prm, tmp_buf, pnetwork, &len);
1551 new_packet:
1552 		if (my_len == 0) {
1553 			pbuf = rtw_malloc(MAX_XMIT_EXTBUF_SZ);
1554 			if (pbuf == NULL)
1555 				goto fail;
1556 			prm->buf[buf_idx].pbuf = pbuf;
1557 		}
1558 
1559 		if ((MAX_XMIT_EXTBUF_SZ - (my_len+len+24+4)) > 0) {
1560 			pbuf = rtw_set_fixed_ie(pbuf,
1561 				len, tmp_buf, &my_len);
1562 			prm->buf[buf_idx].len = my_len;
1563 		} else {
1564 			if (my_len == 0) /* not enough space */
1565 				goto fail;
1566 
1567 			my_len = 0;
1568 			buf_idx++;
1569 			goto new_packet;
1570 		}
1571 next:
1572 		plist = get_next(plist);
1573 	} /* while() */
1574 fail:
1575 	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
1576 
1577 	if (tmp_buf)
1578 		rtw_mfree(tmp_buf, MAX_XMIT_EXTBUF_SZ);
1579 
1580 	RTW_INFO("RM: Found %d matched %s\n", matched_network,
1581 		prm->q.opt.bcn.ssid.Ssid);
1582 
1583 	if (prm->buf[buf_idx].pbuf)
1584 		return buf_idx+1;
1585 
1586 	return 0;
1587 }
1588 
issue_beacon_rep(struct rm_obj * prm)1589 int issue_beacon_rep(struct rm_obj *prm)
1590 {
1591 	int i, my_len;
1592 	u8 *pframe;
1593 	_adapter *padapter = prm->psta->padapter;
1594 	struct pkt_attrib *pattr;
1595 	struct xmit_frame *pmgntframe;
1596 	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
1597 	int pkt_num;
1598 
1599 
1600 	pkt_num = retrieve_scan_result(prm);
1601 
1602 	if (pkt_num == 0) {
1603 		issue_null_reply(prm);
1604 		return _SUCCESS;
1605 	}
1606 
1607 	for (i=0;i<pkt_num;i++) {
1608 
1609 		pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1610 		if (pmgntframe == NULL) {
1611 			RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);
1612 			goto fail;
1613 		}
1614 		pattr = &pmgntframe->attrib;
1615 		pframe = build_wlan_hdr(padapter,
1616 			pmgntframe, prm->psta, WIFI_ACTION);
1617 		pframe = rtw_set_fixed_ie(pframe,
1618 			3, &prm->p.category, &pattr->pktlen);
1619 
1620 		my_len = 0;
1621 		pframe = rtw_set_fixed_ie(pframe,
1622 			prm->buf[i].len, prm->buf[i].pbuf, &my_len);
1623 
1624 		pattr->pktlen += my_len;
1625 		pattr->last_txcmdsz = pattr->pktlen;
1626 		dump_mgntframe(padapter, pmgntframe);
1627 	}
1628 fail:
1629 	for (i=0;i<pkt_num;i++) {
1630 		if (prm->buf[i].pbuf) {
1631 			rtw_mfree(prm->buf[i].pbuf, MAX_XMIT_EXTBUF_SZ);
1632 			prm->buf[i].pbuf = NULL;
1633 			prm->buf[i].len = 0;
1634 		}
1635 	}
1636 	return _SUCCESS;
1637 }
1638 
1639 /* neighbor request */
issue_nb_req(struct rm_obj * prm)1640 int issue_nb_req(struct rm_obj *prm)
1641 {
1642 	_adapter *padapter = prm->psta->padapter;
1643 	struct sta_info *psta = prm->psta;
1644 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1645 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1646 	struct xmit_frame *pmgntframe = NULL;
1647 	struct pkt_attrib *pattr = NULL;
1648 	u8 val8;
1649 	u8 *pframe = NULL;
1650 
1651 
1652 	RTW_INFO("RM: %s\n", __func__);
1653 
1654 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1655 	if (pmgntframe == NULL) {
1656 		RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);
1657 		return _FALSE;
1658 	}
1659 	pattr = &pmgntframe->attrib;
1660 	pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);
1661 	pframe = rtw_set_fixed_ie(pframe,
1662 		3, &prm->q.category, &pattr->pktlen);
1663 
1664 	if (prm->q.pssid) {
1665 
1666 		u8 sub_ie[64] = {0};
1667 		u8 *pie = &sub_ie[2];
1668 
1669 		RTW_INFO("RM: Send NB Req to "MAC_FMT" for(SSID) %s searching\n",
1670 			MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
1671 			pmlmepriv->cur_network.network.Ssid.Ssid);
1672 
1673 		val8 = strlen(prm->q.pssid);
1674 		sub_ie[0] = 0; /*SSID*/
1675 		sub_ie[1] = val8;
1676 
1677 		_rtw_memcpy(pie, prm->q.pssid, val8);
1678 
1679 		pframe = rtw_set_fixed_ie(pframe, val8 + 2,
1680 			sub_ie, &pattr->pktlen);
1681 	} else {
1682 
1683 		if (!pmlmepriv->cur_network.network.Ssid.SsidLength)
1684 			RTW_INFO("RM: Send NB Req to "MAC_FMT"\n",
1685 				MAC_ARG(pmlmepriv->cur_network.network.MacAddress));
1686 		else {
1687 			u8 sub_ie[64] = {0};
1688 			u8 *pie = &sub_ie[2];
1689 
1690 			RTW_INFO("RM: Send NB Req to "MAC_FMT" for(SSID) %s searching\n",
1691 				MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
1692 				pmlmepriv->cur_network.network.Ssid.Ssid);
1693 
1694 			sub_ie[0] = 0; /*SSID*/
1695 			sub_ie[1] = pmlmepriv->cur_network.network.Ssid.SsidLength;
1696 
1697 			_rtw_memcpy(pie, pmlmepriv->cur_network.network.Ssid.Ssid,
1698 				pmlmepriv->cur_network.network.Ssid.SsidLength);
1699 
1700 			pframe = rtw_set_fixed_ie(pframe,
1701 				pmlmepriv->cur_network.network.Ssid.SsidLength + 2,
1702 				sub_ie, &pattr->pktlen);
1703 		}
1704 	}
1705 
1706 	pattr->last_txcmdsz = pattr->pktlen;
1707 	dump_mgntframe(padapter, pmgntframe);
1708 
1709 	return _SUCCESS;
1710 }
1711 
1712 /* issue link measurement request */
issue_link_meas_req(struct rm_obj * prm)1713 int issue_link_meas_req(struct rm_obj *prm)
1714 {
1715 	_adapter *padapter = prm->psta->padapter;
1716 	struct sta_info *psta = prm->psta;
1717 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1718 	struct xmit_frame *pmgntframe = NULL;
1719 	struct pkt_attrib *pattr = NULL;
1720 	u8 *pframe = NULL;
1721 	s8 pwr_used, path_a_pwr;
1722 
1723 
1724 	RTW_INFO("RM: %s\n", __func__);
1725 
1726 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1727 	if (pmgntframe == NULL) {
1728 		RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);
1729 		return _FALSE;
1730 	}
1731 	pattr = &pmgntframe->attrib;
1732 	pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);
1733 
1734 	/* Category, Action code, Dialog token */
1735 	pframe = rtw_set_fixed_ie(pframe,
1736 		3, &prm->q.category, &pattr->pktlen);
1737 
1738 	/* xmit power used */
1739 	/* we don't know actual TX power due to RA may change TX rate;
1740 	 * But if we fix TX rate then we can get specific tx power
1741 	 */
1742 	pattr->rate = MGN_6M;
1743 	rm_get_tx_power(padapter, RF_PATH_A, MGN_6M, &pwr_used);
1744 	pframe = rtw_set_fixed_ie(pframe,
1745 		1, &pwr_used, &pattr->pktlen);
1746 
1747 	/* Max xmit power */
1748 	rm_get_path_a_max_tx_power(padapter, &path_a_pwr);
1749 	pframe = rtw_set_fixed_ie(pframe,
1750 		1, &path_a_pwr, &pattr->pktlen);
1751 
1752 	pattr->last_txcmdsz = pattr->pktlen;
1753 	dump_mgntframe(padapter, pmgntframe);
1754 
1755 	return _SUCCESS;
1756 }
1757 
1758 /* issue link measurement report */
issue_link_meas_rep(struct rm_obj * prm)1759 int issue_link_meas_rep(struct rm_obj *prm)
1760 {
1761 	u8 val8;
1762 	u8 *pframe;
1763 	unsigned int my_len;
1764 	_adapter *padapter = prm->psta->padapter;
1765 	struct xmit_frame *pmgntframe;
1766 	struct pkt_attrib *pattr;
1767 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1768 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1769 	struct sta_info *psta = prm->psta;
1770 	int i;
1771 	u8 tpc[4];
1772 	s8 pwr_used;
1773 
1774 
1775 	RTW_INFO("RM: %s\n", __func__);
1776 
1777 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1778 	if (pmgntframe == NULL) {
1779 		RTW_ERR("RM: ERR %s alloc xmit_frame fail\n",__func__);
1780 		return _FALSE;
1781 	}
1782 	pattr = &pmgntframe->attrib;
1783 	pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);
1784 	/* Category, action code, Dialog token */
1785 	pframe = rtw_set_fixed_ie(pframe, 3,
1786 		&prm->p.category, &pattr->pktlen);
1787 
1788 	my_len = 0;
1789 
1790 	/* TPC report */
1791 	rm_get_tx_power(padapter, RF_PATH_A, MGN_6M, &pwr_used);
1792 	tpc[0] = EID_TPC;
1793 	tpc[1] = 2; /* length */
1794 
1795 	/* TX power */
1796 	tpc[2] = pwr_used;
1797 
1798 	/* link margin */
1799 	rm_get_rx_sensitivity(padapter, prm->q.rx_bw, prm->q.rx_rate, &pwr_used);
1800 	tpc[3] = prm->q.rx_pwr - pwr_used; /* RX sensitivity */
1801 	pattr->rate = MGN_6M; /* use fix rate to get fixed RX sensitivity */
1802 
1803 #if (RM_MORE_DBG_MSG)
1804 	RTW_INFO("RM: rx_pwr=%ddBm - rx_sensitivity=%ddBm = link_margin=%ddB\n",
1805 		prm->q.rx_pwr, pwr_used, tpc[3]);
1806 #endif
1807 	pframe = rtw_set_fixed_ie(pframe, 4, tpc, &my_len);
1808 
1809 	/* RECV antenna ID */
1810 	val8 = 0; /* unknown antenna */
1811 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1812 
1813 	/* XMIT antenna ID */
1814 	/* Fix rate 6M(1T) always use main antenna to TX */
1815 	val8 = 1; /* main antenna */
1816 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1817 
1818 	/* RCPI */
1819 	val8 = translate_dbm_to_rcpi(prm->q.rx_pwr);
1820 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1821 
1822 	/* RSNI */
1823 	val8 = prm->q.rx_rsni;
1824 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1825 
1826 	/* length */
1827 	//val8 = (u8)my_len-2;
1828 	//rtw_set_fixed_ie(plen, 1, &val8, &i); /* use variable i to ignore it */
1829 
1830 	pattr->pktlen += my_len;
1831 	pattr->last_txcmdsz = pattr->pktlen;
1832 	dump_mgntframe(padapter, pmgntframe);
1833 
1834 	return _SUCCESS;
1835 }
1836 
rm_gen_bcn_req_s_elem(_adapter * padapter,struct rm_obj * prm,u8 * pframe,unsigned int * fr_len)1837 static u8 *rm_gen_bcn_req_s_elem(_adapter *padapter,
1838 	struct rm_obj *prm, u8 *pframe, unsigned int *fr_len)
1839 {
1840 	u8 val8, l;
1841 	int i;
1842 	unsigned int my_len = 0;
1843 	struct _RT_OPERATING_CLASS *op;
1844 
1845 	/* meas mode */
1846 	val8 = bcn_req_active; /* measurement mode T8-64 */
1847 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1848 
1849 	/* bssid */
1850 	pframe = rtw_set_fixed_ie(pframe, 6, prm->q.bssid, &my_len);
1851 
1852 	/*
1853 	 * opt ssid (0)
1854 	 */
1855 	l = MIN(32, (int)prm->q.opt.bcn.ssid.SsidLength);
1856 
1857 	l = (int)prm->q.opt.bcn.ssid.SsidLength;
1858 
1859 	if (l > 32)
1860 		RTW_ERR("RM: %s SSID len over size %d! skip it!\n",__func__, l);
1861 
1862 	if (l > 0 && l <= 32) {
1863 		/* Type */
1864 		val8 = bcn_req_ssid;
1865 		pframe = rtw_set_fixed_ie(pframe, 1,
1866 			&val8, &my_len);
1867 		/* Len */
1868 		pframe = rtw_set_fixed_ie(pframe, 1,
1869 			&l, &my_len);
1870 		/* Value */
1871 		pframe = rtw_set_fixed_ie(pframe, l,
1872 			prm->q.opt.bcn.ssid.Ssid, &my_len);
1873 	}
1874 
1875 	/*
1876 	 * opt reporting detail (2)
1877 	 */
1878 	/* Type */
1879 	val8 = bcn_req_rep_detail;
1880 	pframe = rtw_set_fixed_ie(pframe, 1,
1881 		&val8, &my_len);
1882 	/* Len */
1883 	l = 1;
1884 	pframe = rtw_set_fixed_ie(pframe, 1,
1885 		&l, &my_len);
1886 	/* Value */
1887 	pframe = rtw_set_fixed_ie(pframe, l,
1888 		&prm->q.opt.bcn.rep_detail, &my_len);
1889 
1890 	/*
1891 	 * opt request (10)
1892 	 */
1893 
1894 	if (prm->q.opt.bcn.req_id_num > 0) {
1895 		/* Type */
1896 		val8 = bcn_req_req;
1897 		pframe = rtw_set_fixed_ie(pframe, 1,
1898 			&val8, &my_len);
1899 		/* Len */
1900 		l = prm->q.opt.bcn.req_id_num;
1901 		pframe = rtw_set_fixed_ie(pframe, 1,
1902 			&l, &my_len);
1903 		/* Value */
1904 		pframe = rtw_set_fixed_ie(pframe, l,
1905 			prm->q.opt.bcn.req_id, &my_len);
1906 	}
1907 
1908 	/*
1909 	 * opt ap channel report (51)
1910 	 */
1911 	for (i = 0; i < prm->q.opt.bcn.ap_ch_rpt_num; i++) {
1912 		op = prm->q.opt.bcn.ap_ch_rpt[i];
1913 		if (op == NULL)
1914 			break;
1915 		/* Type */
1916 		val8 = bcn_req_ap_ch_rep;
1917 		pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1918 		l = (u8)op->Len + 1;
1919 		/* length */
1920 		pframe = rtw_set_fixed_ie(pframe, 1, &l, &my_len);
1921 
1922 		/* op class */
1923 		val8 = op->global_op_class;
1924 		pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1925 		/* channel */
1926 		pframe = rtw_set_fixed_ie(pframe, op->Len, op->Channel, &my_len);
1927 	}
1928 
1929 	/* update length to caller */
1930 	*fr_len += my_len;
1931 
1932 	/* optional subelements */
1933 	return pframe;
1934 }
1935 
rm_gen_ch_load_req_s_elem(_adapter * padapter,u8 * pframe,unsigned int * fr_len)1936 static u8 *rm_gen_ch_load_req_s_elem(_adapter *padapter,
1937 	u8 *pframe, unsigned int *fr_len)
1938 {
1939 	u8 val8;
1940 	unsigned int my_len = 0;
1941 
1942 
1943 	val8 = 1; /* 1: channel load T8-60 */
1944 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1945 
1946 	val8 = 2; /* channel load length = 2 (extensible)  */
1947 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1948 
1949 	val8 = 0; /* channel load condition : 0 (issue when meas done) T8-61 */
1950 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1951 
1952 	val8 = 0; /* channel load reference value : 0 */
1953 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1954 
1955 	/* update length to caller */
1956 	*fr_len += my_len;
1957 
1958 	return pframe;
1959 }
1960 
rm_gen_noise_histo_req_s_elem(_adapter * padapter,u8 * pframe,unsigned int * fr_len)1961 static u8 *rm_gen_noise_histo_req_s_elem(_adapter *padapter,
1962 	u8 *pframe, unsigned int *fr_len)
1963 {
1964 	u8 val8;
1965 	unsigned int my_len = 0;
1966 
1967 
1968 	val8 = 1; /* 1: noise histogram T8-62 */
1969 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1970 
1971 	val8 = 2; /* noise histogram length = 2 (extensible)  */
1972 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1973 
1974 	val8 = 0; /* noise histogram condition : 0 (issue when meas done) T8-63 */
1975 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1976 
1977 	val8 = 0; /* noise histogram reference value : 0 */
1978 	pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
1979 
1980 	/* update length to caller */
1981 	*fr_len += my_len;
1982 
1983 	return pframe;
1984 }
1985 
issue_radio_meas_req(struct rm_obj * prm)1986 int issue_radio_meas_req(struct rm_obj *prm)
1987 {
1988 	u8 val8;
1989 	u8 *pframe;
1990 	u8 *plen;
1991 	u16 val16;
1992 	int my_len, i;
1993 	struct xmit_frame *pmgntframe;
1994 	struct pkt_attrib *pattr;
1995 	_adapter *padapter = prm->psta->padapter;
1996 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1997 
1998 
1999 	RTW_INFO("RM: %s - %s\n", __func__, rm_type_req_name(prm->q.m_type));
2000 
2001 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2002 	if (pmgntframe == NULL) {
2003 		RTW_ERR("RM: %s alloc xmit_frame fail\n",__func__);
2004 		return _FALSE;
2005 	}
2006 	pattr = &pmgntframe->attrib;
2007 	pframe = build_wlan_hdr(padapter, pmgntframe, prm->psta, WIFI_ACTION);
2008 
2009 	/* Category, Action code, Dialog token */
2010 	pframe = rtw_set_fixed_ie(pframe, 3, &prm->q.category, &pattr->pktlen);
2011 
2012 	/* repeat */
2013 	val16 = cpu_to_le16(prm->q.rpt);
2014 	pframe = rtw_set_fixed_ie(pframe, 2,
2015 		(unsigned char *)&(val16), &pattr->pktlen);
2016 
2017 	my_len = 0;
2018 	plen = pframe + 1;
2019 	/* Element ID, Length, Meas token, Meas Mode, Meas type, op class, ch */
2020 	pframe = rtw_set_fixed_ie(pframe, 7, &prm->q.e_id, &my_len);
2021 
2022 	/* random interval */
2023 	val16 = cpu_to_le16(prm->q.rand_intvl); /* TU */
2024 	pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
2025 
2026 	/* measurement duration */
2027 	val16 = cpu_to_le16(prm->q.meas_dur);
2028 	pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
2029 
2030 	/* optional subelement */
2031 	switch (prm->q.m_type) {
2032 	case bcn_req:
2033 		pframe = rm_gen_bcn_req_s_elem(padapter, prm,  pframe, &my_len);
2034 		break;
2035 	case ch_load_req:
2036 		pframe = rm_gen_ch_load_req_s_elem(padapter, pframe, &my_len);
2037 		break;
2038 	case noise_histo_req:
2039 		pframe = rm_gen_noise_histo_req_s_elem(padapter,
2040 			pframe, &my_len);
2041 		break;
2042 	case basic_req:
2043 	default:
2044 		break;
2045 	}
2046 
2047 	/* length */
2048 	val8 = (u8)my_len - 2;
2049 	rtw_set_fixed_ie(plen, 1, &val8, &i);
2050 
2051 	pattr->pktlen += my_len;
2052 
2053 	pattr->last_txcmdsz = pattr->pktlen;
2054 	dump_mgntframe(padapter, pmgntframe);
2055 
2056 	return _SUCCESS;
2057 }
2058 
rm_radio_meas_report_cond(struct rm_obj * prm)2059 int rm_radio_meas_report_cond(struct rm_obj *prm)
2060 {
2061 	u8 val8;
2062 	int i;
2063 
2064 
2065 	switch (prm->q.m_type) {
2066 	case ch_load_req:
2067 
2068 		val8 = prm->p.ch_load;
2069 		switch (prm->q.opt.clm.rep_cond.cond) {
2070 		case ch_load_cond_immediately:
2071 			return _SUCCESS;
2072 		case ch_load_cond_anpi_equal_greater:
2073 			if (val8 >= prm->q.opt.clm.rep_cond.threshold)
2074 				return _SUCCESS;
2075 			break;
2076 		case ch_load_cond_anpi_equal_less:
2077 			if (val8 <= prm->q.opt.clm.rep_cond.threshold)
2078 				return _SUCCESS;
2079 			break;
2080 		default:
2081 			break;
2082 		}
2083 		break;
2084 	case noise_histo_req:
2085 		val8 = prm->p.anpi;
2086 		switch (prm->q.opt.nhm.rep_cond.cond) {
2087 		case noise_histo_cond_immediately:
2088 			return _SUCCESS;
2089 		case noise_histo_cond_anpi_equal_greater:
2090 			if (val8 >= prm->q.opt.nhm.rep_cond.threshold)
2091 				return _SUCCESS;
2092 			break;
2093 		case noise_histo_cond_anpi_equal_less:
2094 			if (val8 <= prm->q.opt.nhm.rep_cond.threshold)
2095 				return _SUCCESS;
2096 			break;
2097 		default:
2098 			break;
2099 		}
2100 		break;
2101 	default:
2102 		break;
2103 	}
2104 	return _FAIL;
2105 }
2106 
retrieve_radio_meas_result(struct rm_obj * prm)2107 int retrieve_radio_meas_result(struct rm_obj *prm)
2108 {
2109 	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(prm->psta->padapter);
2110 	int i, ch = -1;
2111 	u8 val8;
2112 
2113 
2114 	ch = rtw_chset_search_ch(adapter_to_chset(prm->psta->padapter),
2115 		prm->q.ch_num);
2116 
2117 	if ((ch == -1) || (ch >= MAX_CHANNEL_NUM)) {
2118 		RTW_ERR("RM: get ch(CH:%d) fail\n", prm->q.ch_num);
2119 		ch = 0;
2120 	}
2121 
2122 	switch (prm->q.m_type) {
2123 	case ch_load_req:
2124 #ifdef CONFIG_RTW_ACS
2125 		val8 = hal_data->acs.clm_ratio[ch];
2126 #else
2127 		val8 = 0;
2128 #endif
2129 		prm->p.ch_load = val8;
2130 		break;
2131 	case noise_histo_req:
2132 #ifdef CONFIG_RTW_ACS
2133 		/* ANPI */
2134 		prm->p.anpi = hal_data->acs.nhm_ratio[ch];
2135 
2136 		/* IPI 0~10 */
2137 		for (i=0;i<11;i++)
2138 			prm->p.ipi[i] = hal_data->acs.nhm[ch][i];
2139 
2140 #else
2141 		val8 = 0;
2142 		prm->p.anpi = val8;
2143 		for (i=0;i<11;i++)
2144 			prm->p.ipi[i] = val8;
2145 #endif
2146 		break;
2147 	default:
2148 		break;
2149 	}
2150 	return _SUCCESS;
2151 }
2152 
issue_radio_meas_rep(struct rm_obj * prm)2153 int issue_radio_meas_rep(struct rm_obj *prm)
2154 {
2155 	u8 val8;
2156 	u8 *pframe;
2157 	u8 *plen;
2158 	u16 val16;
2159 	u64 val64;
2160 	unsigned int my_len;
2161 	_adapter *padapter = prm->psta->padapter;
2162 	struct xmit_frame *pmgntframe;
2163 	struct pkt_attrib *pattr;
2164 	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2165 	struct sta_info *psta = prm->psta;
2166 	int i;
2167 
2168 
2169 	RTW_INFO("RM: %s\n", __func__);
2170 
2171 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2172 	if (pmgntframe == NULL) {
2173 		RTW_ERR("RM: ERR %s alloc xmit_frame fail\n",__func__);
2174 		return _FALSE;
2175 	}
2176 	pattr = &pmgntframe->attrib;
2177 	pframe = build_wlan_hdr(padapter, pmgntframe, psta, WIFI_ACTION);
2178 	pframe = rtw_set_fixed_ie(pframe, 3,
2179 		&prm->p.category, &pattr->pktlen);
2180 
2181 	my_len = 0;
2182 	plen = pframe + 1;
2183 	pframe = rtw_set_fixed_ie(pframe, 7, &prm->p.e_id, &my_len);
2184 
2185 	/* Actual Meas start time - 8 bytes */
2186 	val64 = cpu_to_le64(prm->meas_start_time);
2187 	pframe = rtw_set_fixed_ie(pframe, 8, (u8 *)&val64, &my_len);
2188 
2189 	/* measurement duration */
2190 	val16 = prm->meas_end_time - prm->meas_start_time;
2191 	val16 = cpu_to_le16(val16);
2192 	pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
2193 
2194 	/* optional subelement */
2195 	switch (prm->q.m_type) {
2196 	case ch_load_req:
2197 		val8 = prm->p.ch_load;
2198 		pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
2199 		break;
2200 	case noise_histo_req:
2201 		/*
2202 		 * AntennaID
2203 		 * 0: unknown
2204 		 * 255: multiple antenna (Diversity)
2205 		 */
2206 		val8 = 0;
2207 		pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
2208 		/* ANPI */
2209 		val8 = prm->p.anpi;
2210 		pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
2211 		/* IPI 0~10 */
2212 		for (i=0;i<11;i++) {
2213 			val8 = prm->p.ipi[i];
2214 			pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
2215 		}
2216 		break;
2217 	default:
2218 		break;
2219 	}
2220 	/* length */
2221 	val8 = (u8)my_len-2;
2222 	rtw_set_fixed_ie(plen, 1, &val8, &i); /* use variable i to ignore it */
2223 
2224 	pattr->pktlen += my_len;
2225 	pattr->last_txcmdsz = pattr->pktlen;
2226 	dump_mgntframe(padapter, pmgntframe);
2227 
2228 	return _SUCCESS;
2229 }
2230 
rtw_ap_parse_sta_rm_en_cap(_adapter * padapter,struct sta_info * psta,struct rtw_ieee802_11_elems * elem)2231 void rtw_ap_parse_sta_rm_en_cap(_adapter *padapter,
2232 	struct sta_info *psta, struct rtw_ieee802_11_elems *elem)
2233 {
2234 	if (elem->rm_en_cap) {
2235 		RTW_INFO("assoc.rm_en_cap="RM_CAP_FMT"\n",
2236 			RM_CAP_ARG(elem->rm_en_cap));
2237 
2238 		_rtw_memcpy(psta->rm_en_cap, (elem->rm_en_cap),
2239 			MIN(elem->rm_en_cap_len, sizeof(psta->rm_en_cap)));
2240 	}
2241 }
2242 
RM_IE_handler(_adapter * padapter,PNDIS_802_11_VARIABLE_IEs pIE)2243 void RM_IE_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
2244 {
2245 	int i;
2246 
2247 	_rtw_memcpy(&padapter->rmpriv.rm_en_cap_assoc, pIE->data,
2248 		    MIN(pIE->Length, sizeof(padapter->rmpriv.rm_en_cap_assoc)));
2249 	RTW_INFO("assoc.rm_en_cap="RM_CAP_FMT"\n", RM_CAP_ARG(pIE->data));
2250 }
2251 
2252 /* Debug command */
2253 
2254 #if (RM_SUPPORT_IWPRIV_DBG)
hex2num(char c)2255 static int hex2num(char c)
2256 {
2257 	if (c >= '0' && c <= '9')
2258 		return c - '0';
2259 	if (c >= 'a' && c <= 'f')
2260 		return c - 'a' + 10;
2261 	if (c >= 'A' && c <= 'F')
2262 		return c - 'A' + 10;
2263 	return -1;
2264 }
2265 
hex2byte(const char * hex)2266 int hex2byte(const char *hex)
2267 {
2268 	int a, b;
2269 	a = hex2num(*hex++);
2270 	if (a < 0)
2271 		return -1;
2272 	b = hex2num(*hex++);
2273 	if (b < 0)
2274 		return -1;
2275 	return (a << 4) | b;
2276 }
2277 
hwaddr_parse(char * txt,u8 * addr)2278 static char * hwaddr_parse(char *txt, u8 *addr)
2279 {
2280 	size_t i;
2281 
2282 	for (i = 0; i < ETH_ALEN; i++) {
2283 		int a;
2284 
2285 		a = hex2byte(txt);
2286 		if (a < 0)
2287 			return NULL;
2288 		txt += 2;
2289 		addr[i] = a;
2290 		if (i < ETH_ALEN - 1 && *txt++ != ':')
2291 			return NULL;
2292 	}
2293 	return txt;
2294 }
2295 
rm_dbg_list_sta(_adapter * padapter,char * s)2296 void rm_dbg_list_sta(_adapter *padapter, char *s)
2297 {
2298 	int i;
2299 	_irqL irqL;
2300 	struct sta_info *psta;
2301 	struct sta_priv *pstapriv = &padapter->stapriv;
2302 	_list *plist, *phead;
2303 
2304 
2305 	sprintf(pstr(s), "\n");
2306 	_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
2307 	for (i = 0; i < NUM_STA; i++) {
2308 		phead = &(pstapriv->sta_hash[i]);
2309 		plist = get_next(phead);
2310 
2311 		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
2312 			psta = LIST_CONTAINOR(plist,
2313 				struct sta_info, hash_list);
2314 
2315 			plist = get_next(plist);
2316 
2317 			sprintf(pstr(s), "=========================================\n");
2318 			sprintf(pstr(s), "mac=" MAC_FMT "\n",
2319 				MAC_ARG(psta->cmn.mac_addr));
2320 			sprintf(pstr(s), "state=0x%x, aid=%d, macid=%d\n",
2321 				psta->state, psta->cmn.aid, psta->cmn.mac_id);
2322 			sprintf(pstr(s), "rm_cap="RM_CAP_FMT"\n",
2323 				RM_CAP_ARG(psta->rm_en_cap));
2324 		}
2325 
2326 	}
2327 	_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
2328 	sprintf(pstr(s), "=========================================\n");
2329 }
2330 
rm_dbg_help(_adapter * padapter,char * s)2331 void rm_dbg_help(_adapter *padapter, char *s)
2332 {
2333 	int i;
2334 
2335 
2336 	sprintf(pstr(s), "\n");
2337 	sprintf(pstr(s), "rrm list_sta\n");
2338 	sprintf(pstr(s), "rrm list_meas\n");
2339 
2340 	sprintf(pstr(s), "rrm add_meas <aid=1|mac=>,m=<bcn|clm|nhm|nb|link>,rpt=\n");
2341 	sprintf(pstr(s), "rrm run_meas <aid=1|evid=>\n");
2342 	sprintf(pstr(s), "rrm del_meas\n");
2343 
2344 	sprintf(pstr(s), "rrm run_meas rmid=xxxx,ev=xx\n");
2345 	sprintf(pstr(s), "rrm activate\n");
2346 
2347 	for (i=0;i<RM_EV_max;i++)
2348 		sprintf(pstr(s), "\t%2d %s\n",i, rm_event_name(i) );
2349 	sprintf(pstr(s), "\n");
2350 }
2351 
rm_get_sta(_adapter * padapter,u16 aid,u8 * pbssid)2352 struct sta_info *rm_get_sta(_adapter *padapter, u16 aid, u8* pbssid)
2353 {
2354 	int i;
2355 	_irqL irqL;
2356 	struct sta_info *psta = NULL;
2357 	struct sta_priv *pstapriv = &padapter->stapriv;
2358 	_list *plist, *phead;
2359 
2360 
2361 	_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
2362 
2363 	for (i = 0; i < NUM_STA; i++) {
2364 		phead = &(pstapriv->sta_hash[i]);
2365 		plist = get_next(phead);
2366 
2367 		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
2368 			psta = LIST_CONTAINOR(plist,
2369 				struct sta_info, hash_list);
2370 
2371 			plist = get_next(plist);
2372 
2373 			if (psta->cmn.aid == aid)
2374 				goto done;
2375 
2376 			if (pbssid && _rtw_memcmp(psta->cmn.mac_addr,
2377 				pbssid, 6))
2378 				goto done;
2379 		}
2380 
2381 	}
2382 	psta = NULL;
2383 done:
2384 	_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
2385 	return psta;
2386 }
2387 
rm_dbg_modify_meas(_adapter * padapter,char * s)2388 static int rm_dbg_modify_meas(_adapter *padapter, char *s)
2389 {
2390 	struct rm_priv *prmpriv = &padapter->rmpriv;
2391 	struct rm_obj *prm;
2392 	struct sta_info *psta;
2393 	char *pmac, *ptr, *paid, *prpt, *pnbp, *pclm, *pnhm, *pbcn, *plnk;
2394 	unsigned val;
2395 	u8 bssid[ETH_ALEN];
2396 
2397 
2398 	/* example :
2399 	* rrm add_meas <aid=1|mac=>,m=<nb|clm|nhm|bcn|link>,<rept=>
2400 	* rrm run_meas <aid=1|evid=>
2401 	*/
2402 	paid = strstr(s, "aid=");
2403 	pmac = strstr(s, "mac=");
2404 	pbcn = strstr(s, "m=bcn");
2405 	pclm = strstr(s, "m=clm");
2406 	pnhm = strstr(s, "m=nhm");
2407 	pnbp = strstr(s, "m=nb");
2408 	plnk = strstr(s, "m=link");
2409 	prpt = strstr(s, "rpt=");
2410 
2411 	/* set all ',' to NULL (end of line) */
2412 	ptr = s;
2413 	while (ptr) {
2414 		ptr = strchr(ptr, ',');
2415 		if (ptr) {
2416 			*(ptr) = 0x0;
2417 			ptr++;
2418 		}
2419 	}
2420 	prm = (struct rm_obj *)prmpriv->prm_sel;
2421 	prm->q.m_token = rm_gen_meas_token(padapter);
2422 	psta = prm->psta;
2423 
2424 	if (paid) { /* find sta_info according to aid */
2425 		paid += 4; /* skip aid= */
2426 		sscanf(paid, "%u", &val); /* aid=x */
2427 		psta = rm_get_sta(padapter, val, NULL);
2428 
2429 	} else if (pmac) { /* find sta_info according to bssid */
2430 		pmac += 4; /* skip mac= */
2431 		if (hwaddr_parse(pmac, bssid) == NULL) {
2432 			sprintf(pstr(s), "Err: \nincorrect mac format\n");
2433 			return _FAIL;
2434 		}
2435 		psta = rm_get_sta(padapter, 0xff, bssid);
2436 	}
2437 
2438 	if (psta) {
2439 		prm->psta = psta;
2440 		prm->q.diag_token = rm_gen_dialog_token(padapter);
2441 		prm->rmid = rm_gen_rmid(padapter, prm, RM_MASTER);
2442 	} else
2443 		return _FAIL;
2444 
2445 	prm->q.action_code = RM_ACT_RADIO_MEAS_REQ;
2446 	if (pbcn) {
2447 		prm->q.m_type = bcn_req;
2448 		prm->q.rand_intvl = le16_to_cpu(100);
2449 		prm->q.meas_dur = le16_to_cpu(100);
2450 	} else if (pnhm) {
2451 		prm->q.m_type = noise_histo_req;
2452 	} else if (pclm) {
2453 		prm->q.m_type = ch_load_req;
2454 	} else if (pnbp) {
2455 		prm->q.action_code = RM_ACT_NB_REP_REQ;
2456 	} else if (plnk) {
2457 		prm->q.action_code = RM_ACT_LINK_MEAS_REQ;
2458 	} else
2459 		return _FAIL;
2460 
2461 	if (prpt) {
2462 		prpt += 4; /* skip rpt= */
2463 		sscanf(prpt, "%u", &val);
2464 		prm->q.rpt = (u8)val;
2465 	}
2466 
2467 	return _SUCCESS;
2468 }
2469 
rm_dbg_activate_meas(_adapter * padapter,char * s)2470 static void rm_dbg_activate_meas(_adapter *padapter, char *s)
2471 {
2472 	struct rm_priv *prmpriv = &(padapter->rmpriv);
2473 	struct rm_obj *prm;
2474 
2475 
2476 	if (prmpriv->prm_sel == NULL) {
2477 		sprintf(pstr(s), "\nErr: No inActivate measurement\n");
2478 		return;
2479 	}
2480 	prm = (struct rm_obj *)prmpriv->prm_sel;
2481 
2482 	/* verify attributes */
2483 	if (prm->psta == NULL) {
2484 		sprintf(pstr(s), "\nErr: inActivate meas has no psta\n");
2485 		return;
2486 	}
2487 
2488 	/* measure current channel */
2489 	prm->q.ch_num = padapter->mlmeextpriv.cur_channel;
2490 	prm->q.op_class = rm_get_oper_class_via_ch(prm->q.ch_num);
2491 
2492 	/* enquee rmobj */
2493 	rm_enqueue_rmobj(padapter, prm, _FALSE);
2494 
2495 	sprintf(pstr(s), "\nActivate rmid=%x, state=%s, meas_type=%s\n",
2496 		prm->rmid, rm_state_name(prm->state),
2497 		rm_type_req_name(prm->q.m_type));
2498 
2499 	sprintf(pstr(s), "aid=%d, mac=" MAC_FMT "\n",
2500 		prm->psta->cmn.aid, MAC_ARG(prm->psta->cmn.mac_addr));
2501 
2502 	/* clearn inActivate prm info */
2503 	prmpriv->prm_sel = NULL;
2504 }
2505 
2506 /* 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)2507 int rm_send_bcn_reqs(_adapter *padapter, u8 *sta_addr, u8 op_class, u8 ch,
2508 	u16 measure_duration, u8 measure_mode, u8 *bssid, u8 *ssid,
2509 	u8 reporting_detail,
2510 	u8 n_ap_ch_rpt, struct _RT_OPERATING_CLASS *rpt,
2511 	u8 n_elem_id, u8 *elem_id_list)
2512 
2513 {
2514 	struct rm_obj *prm;
2515 	char *pact;
2516 	struct sta_info *psta;
2517 	struct _RT_OPERATING_CLASS *prpt;
2518 	void *ptr;
2519 	int i,j,sz;
2520 	u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2521 
2522 
2523 	if (n_ap_ch_rpt > BCN_REQ_OPT_AP_CH_RPT_MAX_NUM) {
2524 		RTW_ERR("RM: chset num %d > %d\n",
2525 			n_ap_ch_rpt, BCN_REQ_OPT_AP_CH_RPT_MAX_NUM);
2526 		return -1;
2527 	}
2528 	/* dest sta */
2529 	psta = rtw_get_stainfo(&padapter->stapriv, sta_addr);
2530         if (!psta) {
2531 		RTW_ERR("RM: psta not found\n");
2532 		return -2;
2533         }
2534 	prm = rm_alloc_rmobj(padapter);
2535 	if (prm == NULL) {
2536 		RTW_ERR("RM: unable to alloc rm obj for requeset\n");
2537 		return -3;
2538 	}
2539 
2540 	prm->psta = psta;
2541 	prm->q.meas_dur = measure_duration;
2542 
2543 	/* Figure 8-104 Measurement Requested format */
2544 	prm->q.category = RTW_WLAN_CATEGORY_RADIO_MEAS;
2545 	prm->q.action_code = RM_ACT_RADIO_MEAS_REQ;
2546 	prm->q.m_mode = measure_mode;
2547 	prm->q.m_type = bcn_req;
2548 	prm->q.diag_token = rm_gen_dialog_token(padapter);
2549 	prm->q.m_token = rm_gen_meas_token(padapter);
2550 	prm->rmid = rm_gen_rmid(padapter, prm, RM_MASTER);
2551 
2552 	prm->q.e_id = _MEAS_REQ_IE_; /* 38 */
2553 	prm->q.ch_num = ch;
2554 	prm->q.op_class = op_class;
2555 	prm->from_ioctl = true;
2556 
2557 	if (bssid != NULL)
2558 		memcpy(prm->q.bssid, bssid, ETH_ALEN);
2559 	else
2560 		memcpy(prm->q.bssid, bcast, ETH_ALEN);
2561 
2562 	if (ssid != NULL) {
2563 		i = MIN(32, strlen(ssid));
2564 		prm->q.opt.bcn.ssid.SsidLength = i;
2565 		memcpy(prm->q.opt.bcn.ssid.Ssid, ssid, i);
2566 	}
2567 
2568 	if (n_ap_ch_rpt > 0) {
2569 		prm->q.opt.bcn.ap_ch_rpt_num = n_ap_ch_rpt;
2570 		j = 0;
2571 		for (i = 0; i < n_ap_ch_rpt; i++) {
2572 			prpt = rpt++;
2573 			if (prpt == NULL)
2574 				break;
2575 
2576 			sz = sizeof(struct _RT_OPERATING_CLASS) * prpt->Len;
2577 			ptr = rtw_malloc(sz);
2578 			_rtw_memcpy(ptr, prpt, sz);
2579 			prm->q.opt.bcn.ap_ch_rpt[i] = (struct _RT_OPERATING_CLASS *)ptr;
2580 		}
2581 	}
2582 	prm->q.opt.bcn.rep_detail = reporting_detail;
2583 
2584 	if ((n_elem_id > 0) && (n_elem_id < BCN_REQ_REQ_OPT_MAX_NUM)) {
2585 		prm->q.opt.bcn.req_id_num = n_elem_id;
2586 		_rtw_memcpy(prm->q.opt.bcn.req_id, elem_id_list, n_elem_id);
2587 	}
2588 	/* enquee rmobj */
2589 	rm_enqueue_rmobj(padapter, prm, _FALSE);
2590 
2591 	RTW_INFO("\nAdd rmid=%x, meas_type=%s ok\n",
2592 		prm->rmid, rm_type_req_name(prm->q.m_type));
2593 
2594 	if (prm->psta)
2595 		RTW_INFO("mac="MAC_FMT"\n", MAC_ARG(prm->psta->cmn.mac_addr));
2596 	return 0;
2597 }
2598 
indicate_beacon_report(u8 * sta_addr,u8 n_measure_rpt,u32 elem_len,u8 * elem)2599 void indicate_beacon_report(u8 *sta_addr,
2600 	u8 n_measure_rpt, u32 elem_len, u8 *elem)
2601 {
2602 	RTW_INFO("RM: recv bcn reprot from mac="MAC_FMT"\n", MAC_ARG(sta_addr));
2603 #ifdef CONFIG_PLATFORM_CMAP_INTFS
2604 	cmap_intfs_nl_beacon_report_event(sta_addr, n_measure_rpt, elem_len, elem);
2605 #endif
2606 }
2607 
rm_dbg_add_meas(_adapter * padapter,char * s)2608 static void rm_dbg_add_meas(_adapter *padapter, char *s)
2609 {
2610 	struct rm_priv *prmpriv = &(padapter->rmpriv);
2611 	struct rm_obj *prm;
2612 	char *pact;
2613 
2614 
2615 	/* example :
2616 	* rrm add_meas <aid=1|mac=>,m=<nb|clm|nhm|link>
2617 	* rrm run_meas <aid=1|evid=>
2618 	*/
2619 	prm = (struct rm_obj *)prmpriv->prm_sel;
2620 	if (prm == NULL)
2621 		prm = rm_alloc_rmobj(padapter);
2622 
2623 	if (prm == NULL) {
2624 		sprintf(pstr(s), "\nErr: alloc meas fail\n");
2625 		return;
2626 	}
2627 
2628         prmpriv->prm_sel = prm;
2629 
2630 	pact = strstr(s, "act");
2631 	if (rm_dbg_modify_meas(padapter, s) == _FAIL) {
2632 
2633 		sprintf(pstr(s), "\nErr: add meas fail\n");
2634 		rm_free_rmobj(prm);
2635 		prmpriv->prm_sel = NULL;
2636 		return;
2637 	}
2638 	prm->q.category = RTW_WLAN_CATEGORY_RADIO_MEAS;
2639 	prm->q.e_id = _MEAS_REQ_IE_; /* 38 */
2640 
2641 	sprintf(pstr(s), "\nAdd rmid=%x, meas_type=%s ok\n",
2642 		prm->rmid, rm_type_req_name(prm->q.m_type));
2643 
2644 	if (prm->psta)
2645 		sprintf(pstr(s), "mac="MAC_FMT"\n",
2646 			MAC_ARG(prm->psta->cmn.mac_addr));
2647 
2648 	if (pact)
2649 		rm_dbg_activate_meas(padapter, pstr(s));
2650 }
2651 
rm_dbg_del_meas(_adapter * padapter,char * s)2652 static void rm_dbg_del_meas(_adapter *padapter, char *s)
2653 {
2654 	struct rm_priv *prmpriv = &padapter->rmpriv;
2655 	struct rm_obj *prm = (struct rm_obj *)prmpriv->prm_sel;
2656 
2657 
2658 	if (prm) {
2659 		sprintf(pstr(s), "\ndelete rmid=%x\n",prm->rmid);
2660 
2661 		/* free inActivate meas - enqueue yet  */
2662 		prmpriv->prm_sel = NULL;
2663 		rtw_mfree(prmpriv->prm_sel, sizeof(struct rm_obj));
2664 	} else
2665 		sprintf(pstr(s), "Err: no inActivate measurement\n");
2666 }
2667 
rm_dbg_run_meas(_adapter * padapter,char * s)2668 static void rm_dbg_run_meas(_adapter *padapter, char *s)
2669 {
2670 	struct rm_obj *prm;
2671 	char *pevid, *prmid;
2672 	u32 rmid, evid;
2673 
2674 
2675 	prmid = strstr(s, "rmid="); /* hex */
2676 	pevid = strstr(s, "evid="); /* dec */
2677 
2678 	if (prmid && pevid) {
2679 		prmid += 5; /* rmid= */
2680 		sscanf(prmid, "%x", &rmid);
2681 
2682 		pevid += 5; /* evid= */
2683 		sscanf(pevid, "%u", &evid);
2684 	} else {
2685 		sprintf(pstr(s), "\nErr: incorrect attribute\n");
2686 		return;
2687 	}
2688 
2689 	prm = rm_get_rmobj(padapter, rmid);
2690 
2691 	if (!prm) {
2692 		sprintf(pstr(s), "\nErr: measurement not found\n");
2693 		return;
2694 	}
2695 
2696 	if (evid >= RM_EV_max) {
2697 		sprintf(pstr(s), "\nErr: wrong event id\n");
2698 		return;
2699 	}
2700 
2701 	rm_post_event(padapter, prm->rmid, evid);
2702 	sprintf(pstr(s), "\npost %s to rmid=%x\n",rm_event_name(evid), rmid);
2703 }
2704 
rm_dbg_show_meas(struct rm_obj * prm,char * s)2705 static void rm_dbg_show_meas(struct rm_obj *prm, char *s)
2706 {
2707 	struct sta_info *psta;
2708 
2709 	psta = prm->psta;
2710 
2711 	if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
2712 
2713 		sprintf(pstr(s), "\nrmid=%x, meas_type=%s\n",
2714 			prm->rmid, rm_type_req_name(prm->q.m_type));
2715 
2716 	} else  if (prm->q.action_code == RM_ACT_NB_REP_REQ) {
2717 
2718 		sprintf(pstr(s), "\nrmid=%x, action=neighbor_req\n",
2719 			prm->rmid);
2720 	} else
2721 		sprintf(pstr(s), "\nrmid=%x, action=unknown\n",
2722 			prm->rmid);
2723 
2724 	if (psta)
2725 		sprintf(pstr(s), "aid=%d, mac="MAC_FMT"\n",
2726 			psta->cmn.aid, MAC_ARG(psta->cmn.mac_addr));
2727 
2728 	sprintf(pstr(s), "clock=%d, state=%s, rpt=%u/%u\n",
2729 		(int)ATOMIC_READ(&prm->pclock->counter),
2730 		rm_state_name(prm->state), prm->p.rpt, prm->q.rpt);
2731 }
2732 
rm_dbg_list_meas(_adapter * padapter,char * s)2733 static void rm_dbg_list_meas(_adapter *padapter, char *s)
2734 {
2735 	int meas_amount;
2736 	_irqL irqL;
2737 	struct rm_obj *prm;
2738 	struct sta_info *psta;
2739 	struct rm_priv *prmpriv = &padapter->rmpriv;
2740 	_queue *queue = &prmpriv->rm_queue;
2741 	_list *plist, *phead;
2742 
2743 
2744 	sprintf(pstr(s), "\n");
2745 	_enter_critical(&queue->lock, &irqL);
2746 	phead = get_list_head(queue);
2747 	plist = get_next(phead);
2748 	meas_amount = 0;
2749 
2750 	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
2751 		prm = LIST_CONTAINOR(plist, struct rm_obj, list);
2752 		meas_amount++;
2753 		plist = get_next(plist);
2754 		psta = prm->psta;
2755 		sprintf(pstr(s), "=========================================\n");
2756 
2757 		rm_dbg_show_meas(prm, s);
2758 	}
2759 	_exit_critical(&queue->lock, &irqL);
2760 
2761 	sprintf(pstr(s), "=========================================\n");
2762 
2763 	if (meas_amount==0) {
2764 		sprintf(pstr(s), "No Activate measurement\n");
2765 		sprintf(pstr(s), "=========================================\n");
2766 	}
2767 
2768 	if (prmpriv->prm_sel == NULL)
2769 		sprintf(pstr(s), "\nNo inActivate measurement\n");
2770 	else {
2771 		sprintf(pstr(s), "\ninActivate measurement\n");
2772 		rm_dbg_show_meas((struct rm_obj *)prmpriv->prm_sel, s);
2773 	}
2774 }
2775 #endif /* RM_SUPPORT_IWPRIV_DBG */
2776 
verify_bcn_req(_adapter * padapter,struct sta_info * psta)2777 int verify_bcn_req(_adapter *padapter, struct sta_info *psta)
2778 {
2779 	char *bssid =  NULL;
2780 	char ssid[] = "RealKungFu";
2781 	u8 op_class = 0;
2782 	u8 ch = 255;
2783 	u16 measure_duration = 100;
2784 	u8 reporting_detaial = 0;
2785 	u8 n_ap_ch_rpt = 6;
2786 	u8 measure_mode = bcn_req_active;
2787 	u8 req[] = {1,2,3};
2788 	u8 req_len = sizeof(req);
2789 
2790 
2791 	static RT_OPERATING_CLASS US[] = {
2792 	/* 0, OP_CLASS_NULL */	//{  0,  0, {}},
2793 	/* 1, OP_CLASS_1 */	{115,  4, {36, 40, 44, 48}},
2794 	/* 2, OP_CLASS_2 */	{118,  4, {52, 56, 60, 64}},
2795 	/* 3, OP_CLASS_3 */	{124,  4, {149, 153, 157, 161}},
2796 	/* 4, OP_CLASS_4 */	{121, 11, {100, 104, 108, 112, 116, 120, 124,
2797 						128, 132, 136, 140}},
2798 	/* 5, OP_CLASS_5 */	{125,  5, {149, 153, 157, 161, 165}},
2799 	/* 6, OP_CLASS_12 */	{ 81, 11, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}
2800 	};
2801 
2802 	rm_send_bcn_reqs(padapter, psta->cmn.mac_addr, op_class, ch,
2803 		measure_duration, measure_mode, bssid, ssid,
2804 		reporting_detaial, n_ap_ch_rpt, US, req_len, req);
2805 	return 0;
2806 }
2807 
rm_dbg_cmd(_adapter * padapter,char * s)2808 void rm_dbg_cmd(_adapter *padapter, char *s)
2809 {
2810 	unsigned val;
2811 	char *paid;
2812 	struct sta_info *psta=NULL;
2813 
2814 #if (RM_SUPPORT_IWPRIV_DBG)
2815 	if (_rtw_memcmp(s, "help", 4)) {
2816 		rm_dbg_help(padapter, s);
2817 
2818 	} else if (_rtw_memcmp(s, "send_bcn_req", 12)) {
2819 
2820 		/* rtwpriv wls1 rrm send_bcn_req aid=1 */
2821 		paid = strstr(s, "aid=");
2822 		if (paid) { /* find sta_info according to aid */
2823 			paid += 4; /* skip aid= */
2824 			sscanf(paid, "%u", &val); /* aid=x */
2825 			psta = rm_get_sta(padapter, val, NULL);
2826 
2827 			if (psta)
2828 				verify_bcn_req(padapter, psta);
2829 		}
2830 
2831 	} else if (_rtw_memcmp(s, "list_sta", 8)) {
2832 		rm_dbg_list_sta(padapter, s);
2833 
2834 	} else if (_rtw_memcmp(s, "list_meas", 9)) {
2835 		rm_dbg_list_meas(padapter, s);
2836 
2837 	} else if (_rtw_memcmp(s, "add_meas", 8)) {
2838 		rm_dbg_add_meas(padapter, s);
2839 
2840 	} else if (_rtw_memcmp(s, "del_meas", 8)) {
2841 		rm_dbg_del_meas(padapter, s);
2842 
2843 	} else if (_rtw_memcmp(s, "activate", 8)) {
2844 		rm_dbg_activate_meas(padapter, s);
2845 
2846 	} else if (_rtw_memcmp(s, "run_meas", 8)) {
2847 		rm_dbg_run_meas(padapter, s);
2848 
2849 	} else if (_rtw_memcmp(s, "nb", 2)) {
2850 
2851 		paid = strstr(s, "aid=");
2852 
2853 		if (paid) { /* find sta_info according to aid */
2854 			paid += 4; /* skip aid= */
2855 			sscanf(paid, "%u", &val); /* aid=x */
2856 			psta = rm_get_sta(padapter, val, NULL);
2857 
2858 			if (psta)
2859 				rm_add_nb_req(padapter, psta);
2860 		}
2861 	}
2862 #else
2863 	sprintf(pstr(s), "\n");
2864 	sprintf(pstr(s), "rrm debug command was disabled\n");
2865 #endif
2866 }
2867 #endif /* CONFIG_RTW_80211K */
2868