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