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