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