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