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