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