1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#define _RTW_MLME_EXT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <wifi.h>
20#include <rtw_mlme_ext.h>
21#include <wlan_bssdef.h>
22#include <mlme_osdep.h>
23#include <recv_osdep.h>
24#include <linux/ieee80211.h>
25#include <rtl8723a_hal.h>
26
27static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
28static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
29static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
30static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
31static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
32static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
33static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
34static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
35static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
36static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
37static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
38
39static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
40static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
41static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
42static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
43static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
44static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
45static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
46static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
47
48static void issue_assocreq(struct rtw_adapter *padapter);
49static void issue_probereq(struct rtw_adapter *padapter,
50 struct cfg80211_ssid *pssid, u8 *da);
51static int issue_probereq_ex(struct rtw_adapter *padapter,
52 struct cfg80211_ssid *pssid,
53 u8 *da, int try_cnt, int wait_ms);
54static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da,
55 u8 is_valid_p2p_probereq);
56static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
57 unsigned short status);
58static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
59 unsigned short reason, int try_cnt, int wait_ms);
60static void start_clnt_assoc(struct rtw_adapter *padapter);
61static void start_clnt_auth(struct rtw_adapter *padapter);
62static void start_clnt_join(struct rtw_adapter *padapter);
63static void start_create_ibss(struct rtw_adapter *padapter);
64static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
65 struct recv_frame *precv_frame);
66
67#ifdef CONFIG_8723AU_AP_MODE
68static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
69static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
70 struct sta_info *pstat, u16 pkt_type);
71#endif
72
73static struct mlme_handler mlme_sta_tbl[]={
74 {"OnAssocReq23a", &OnAssocReq23a},
75 {"OnAssocRsp23a", &OnAssocRsp23a},
76 {"OnReAssocReq", &OnAssocReq23a},
77 {"OnReAssocRsp", &OnAssocRsp23a},
78 {"OnProbeReq23a", &OnProbeReq23a},
79 {"OnProbeRsp23a", &OnProbeRsp23a},
80
81
82
83
84 {"DoReserved23a", &DoReserved23a},
85 {"DoReserved23a", &DoReserved23a},
86 {"OnBeacon23a", &OnBeacon23a},
87 {"OnATIM", &OnAtim23a},
88 {"OnDisassoc23a", &OnDisassoc23a},
89 {"OnAuth23a", &OnAuth23aClient23a},
90 {"OnDeAuth23a", &OnDeAuth23a},
91 {"OnAction23a", &OnAction23a},
92};
93
94static struct action_handler OnAction23a_tbl[]={
95 {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a},
96 {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos},
97 {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls},
98 {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a},
99 {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a},
100 {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht},
101 {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a},
102 {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm},
103 {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p},
104};
105
106static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
107
108
109
110
111unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
112unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
113unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
114unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
115
116unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
117unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
118
119static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
120
121
122
123
124unsigned char MCS_rate_2R23A[16] = {
125 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
126 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
127unsigned char MCS_rate_1R23A[16] = {
128 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
129 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
130
131
132
133
134
135static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
136
137 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
138
139 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
140
141 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
142
143 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
144
145 {{10, 11, 12, 13}, 4},
146
147 {{}, 0},
148};
149
150static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
151
152 {{}, 0},
153
154 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
155 116, 120, 124, 128, 132, 136, 140}, 19},
156
157 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
158 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
159
160 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
161 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},
162
163 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
164 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
165
166 {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},
167
168 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},
169
170 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},
171
172 {{149, 153, 157, 161, 165}, 5},
173
174 {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
175
176 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
177 116, 136, 140, 149, 153, 157, 161, 165}, 20},
178
179 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
180 116, 120, 124, 149, 153, 157, 161, 165}, 20},
181
182 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
183 116, 120, 124, 128, 132, 136, 140}, 19},
184
185 {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
186
187 {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},
188
189 {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149,
190 153, 157, 161, 165}, 15},
191
192 {{56, 60, 64, 149, 153, 157, 161, 165}, 8},
193
194
195
196
197 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
198 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
199
200 {{36, 40, 44, 48}, 4},
201
202 {{36, 40, 44, 48, 149, 153, 157, 161}, 8},
203};
204
205static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
206
207 {0x02, 0x11},
208 {0x02, 0x0A},
209 {0x01, 0x01},
210 {0x01, 0x00},
211 {0x01, 0x00},
212 {0x03, 0x00},
213 {0x03, 0x00},
214 {0x01, 0x09},
215 {0x03, 0x09},
216 {0x03, 0x00},
217 {0x00, 0x00},
218 {0x02, 0x0F},
219 {0x01, 0x08},
220 {0x02, 0x06},
221 {0x02, 0x0B},
222 {0x02, 0x09},
223 {0x01, 0x01},
224 {0x02, 0x05},
225 {0x01, 0x12},
226 {0x00, 0x04},
227 {0x02, 0x10},
228 {0x00, 0x12},
229 {0x00, 0x13},
230 {0x03, 0x12},
231 {0x05, 0x08},
232 {0x02, 0x08},
233 {0x00, 0x00},
234 {0x00, 0x00},
235 {0x00, 0x00},
236 {0x00, 0x00},
237 {0x00, 0x00},
238 {0x05, 0x04},
239
240 {0x00, 0x00},
241 {0x01, 0x00},
242 {0x02, 0x00},
243 {0x03, 0x00},
244 {0x04, 0x00},
245 {0x02, 0x04},
246 {0x00, 0x01},
247 {0x03, 0x0C},
248 {0x00, 0x0B},
249 {0x00, 0x05},
250 {0x00, 0x00},
251 {0x00, 0x00},
252 {0x00, 0x00},
253 {0x00, 0x00},
254 {0x00, 0x00},
255 {0x00, 0x00},
256 {0x00, 0x06},
257 {0x00, 0x07},
258 {0x00, 0x08},
259 {0x00, 0x09},
260 {0x02, 0x0A},
261 {0x00, 0x02},
262 {0x00, 0x03},
263 {0x03, 0x0D},
264 {0x03, 0x0E},
265 {0x02, 0x0F},
266 {0x00, 0x00},
267 {0x00, 0x00},
268 {0x00, 0x00},
269 {0x00, 0x00},
270 {0x00, 0x00},
271 {0x00, 0x00},
272 {0x02, 0x10},
273 {0x03, 0x00},
274};
275
276static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE =
277{0x03, 0x02};
278
279static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf)
280{
281}
282
283static struct fwevent wlanevents[] =
284{
285 {0, &dummy_event_callback},
286 {0, NULL},
287 {0, NULL},
288 {0, NULL},
289 {0, NULL},
290 {0, NULL},
291 {0, NULL},
292 {0, NULL},
293 {0, &rtw_survey_event_cb23a},
294 {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a},
295 {0, &rtw23a_joinbss_event_cb},
296 {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
297 {sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
298 {0, &dummy_event_callback},
299 {0, &dummy_event_callback},
300 {0, NULL},
301 {0, NULL},
302 {0, NULL},
303 {0, NULL},
304 {0, &dummy_event_callback},
305 {0, NULL},
306 {0, NULL},
307 {0, NULL},
308 {0, &dummy_event_callback},
309 {0, NULL},
310};
311
312
313static void rtw_correct_TSF(struct rtw_adapter *padapter)
314{
315 hw_var_set_correct_tsf(padapter);
316}
317
318static void
319rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt)
320{
321 pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp);
322}
323
324
325
326
327
328
329
330
331int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch)
332{
333 int i;
334
335 for (i = 0; ch_set[i]. ChannelNum != 0; i++) {
336 if (ch == ch_set[i].ChannelNum)
337 break;
338 }
339
340 if (i >= ch_set[i].ChannelNum)
341 return -1;
342 return i;
343}
344
345
346
347
348
349
350
351int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
352{
353 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
354
355 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
356 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
357 return _SUCCESS;
358}
359
360static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter)
361{
362 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
363 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
364 unsigned char mixed_datarate[NumRates] = {
365 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
366 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
367 _48M_RATE_, _54M_RATE_, 0xff};
368 unsigned char mixed_basicrate[NumRates] = {
369 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
370 _12M_RATE_, _24M_RATE_, 0xff,};
371
372 atomic_set(&pmlmeext->event_seq, 0);
373
374 pmlmeext->mgnt_seq = 0;
375
376 pmlmeext->cur_channel = padapter->registrypriv.channel;
377 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
378 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
379
380 pmlmeext->retry = 0;
381
382 pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
383
384 memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
385 memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
386
387 if (pmlmeext->cur_channel > 14)
388 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
389 else
390 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
391
392 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
393 pmlmeext->sitesurvey_res.channel_idx = 0;
394 pmlmeext->sitesurvey_res.bss_cnt = 0;
395 pmlmeext->scan_abort = false;
396
397 pmlmeinfo->state = MSR_NOLINK;
398 pmlmeinfo->reauth_count = 0;
399 pmlmeinfo->reassoc_count = 0;
400 pmlmeinfo->link_count = 0;
401 pmlmeinfo->auth_seq = 0;
402 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
403 pmlmeinfo->key_index = 0;
404 pmlmeinfo->iv = 0;
405
406 pmlmeinfo->enc_algo = 0;
407 pmlmeinfo->authModeToggle = 0;
408
409 memset(pmlmeinfo->chg_txt, 0, 128);
410
411 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
412 pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
413
414 pmlmeinfo->dialogToken = 0;
415
416 pmlmeext->action_public_rxseq = 0xffff;
417 pmlmeext->action_public_dialog_token = 0xff;
418}
419
420static int has_channel(struct rt_channel_info *channel_set,
421 u8 chanset_size, u8 chan) {
422 int i;
423
424 for (i = 0; i < chanset_size; i++) {
425 if (channel_set[i].ChannelNum == chan)
426 return 1;
427 }
428
429 return 0;
430}
431
432static void init_channel_list(struct rtw_adapter *padapter,
433 struct rt_channel_info *channel_set,
434 u8 chanset_size,
435 struct p2p_channels *channel_list)
436{
437 struct p2p_oper_class_map op_class[] = {
438 { IEEE80211G, 81, 1, 13, 1, BW20 },
439 { IEEE80211G, 82, 14, 14, 1, BW20 },
440 { IEEE80211A, 115, 36, 48, 4, BW20 },
441 { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
442 { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
443 { IEEE80211A, 124, 149, 161, 4, BW20 },
444 { IEEE80211A, 125, 149, 169, 4, BW20 },
445 { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
446 { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
447 { -1, 0, 0, 0, 0, BW20 }
448 };
449
450 int cla, op;
451
452 cla = 0;
453
454 for (op = 0; op_class[op].op_class; op++) {
455 u8 ch;
456 struct p2p_oper_class_map *o = &op_class[op];
457 struct p2p_reg_class *reg = NULL;
458
459 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
460 if (!has_channel(channel_set, chanset_size, ch))
461 continue;
462
463 if ((0 == padapter->registrypriv.ht_enable) &&
464 (o->inc == 8))
465 continue;
466
467 if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
468 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
469 continue;
470
471 if (reg == NULL) {
472 reg = &channel_list->reg_class[cla];
473 cla++;
474 reg->reg_class = o->op_class;
475 reg->channels = 0;
476 }
477 reg->channel[reg->channels] = ch;
478 reg->channels++;
479 }
480 }
481 channel_list->reg_classes = cla;
482}
483
484static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan,
485 struct rt_channel_info *c_set)
486{
487 u8 i, ch_size = 0;
488 u8 b5GBand = false, b2_4GBand = false;
489 u8 Index2G = 0, Index5G = 0;
490
491 memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
492
493 if (cplan >= RT_CHANNEL_DOMAIN_MAX &&
494 cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
495 DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan);
496 return ch_size;
497 }
498
499 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
500 b2_4GBand = true;
501 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
502 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
503 else
504 Index2G = RTW_ChannelPlanMap[cplan].Index2G;
505 }
506
507 if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
508 b5GBand = true;
509 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
510 Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
511 else
512 Index5G = RTW_ChannelPlanMap[cplan].Index5G;
513 }
514
515 if (b2_4GBand) {
516 for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) {
517 c_set[ch_size].ChannelNum =
518 RTW_ChannelPlan2G[Index2G].Channel[i];
519
520 if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) ||
521
522 RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) {
523 if (c_set[ch_size].ChannelNum >= 1 &&
524 c_set[ch_size].ChannelNum <= 11)
525 c_set[ch_size].ScanType = SCAN_ACTIVE;
526 else if (c_set[ch_size].ChannelNum >= 12 &&
527 c_set[ch_size].ChannelNum <= 14)
528 c_set[ch_size].ScanType = SCAN_PASSIVE;
529 } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan ||
530 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan ||
531 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
532
533 if (c_set[ch_size].ChannelNum <= 11)
534 c_set[ch_size].ScanType = SCAN_ACTIVE;
535 else
536 c_set[ch_size].ScanType = SCAN_PASSIVE;
537 } else
538 c_set[ch_size].ScanType = SCAN_ACTIVE;
539
540 ch_size++;
541 }
542 }
543
544 if (b5GBand) {
545 for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) {
546 if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 ||
547 RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) {
548 c_set[ch_size].ChannelNum =
549 RTW_ChannelPlan5G[Index5G].Channel[i];
550 if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) {
551
552 c_set[ch_size].ScanType =
553 SCAN_PASSIVE;
554 } else
555 c_set[ch_size].ScanType =
556 SCAN_ACTIVE;
557 DBG_8723A("%s(): channel_set[%d].ChannelNum = "
558 "%d\n", __func__, ch_size,
559 c_set[ch_size].ChannelNum);
560 ch_size++;
561 }
562 }
563 }
564
565 return ch_size;
566}
567
568int init_mlme_ext_priv23a(struct rtw_adapter *padapter)
569{
570 struct registry_priv *pregistrypriv = &padapter->registrypriv;
571 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
572 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
573 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
574
575 pmlmeext->padapter = padapter;
576
577 init_mlme_ext_priv23a_value(padapter);
578 pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
579
580 init_mlme_ext_timer23a(padapter);
581
582#ifdef CONFIG_8723AU_AP_MODE
583 init_mlme_ap_info23a(padapter);
584#endif
585
586 pmlmeext->max_chan_nums = init_channel_set(padapter,
587 pmlmepriv->ChannelPlan,
588 pmlmeext->channel_set);
589 init_channel_list(padapter, pmlmeext->channel_set,
590 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
591
592 pmlmeext->chan_scan_time = SURVEY_TO;
593 pmlmeext->mlmeext_init = true;
594
595 pmlmeext->active_keep_alive_check = true;
596 return _SUCCESS;
597}
598
599void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext)
600{
601 struct rtw_adapter *padapter = pmlmeext->padapter;
602
603 if (!padapter)
604 return;
605
606 if (padapter->bDriverStopped == true) {
607 del_timer_sync(&pmlmeext->survey_timer);
608 del_timer_sync(&pmlmeext->link_timer);
609
610 }
611}
612
613static void
614_mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable,
615 struct recv_frame *precv_frame)
616{
617 struct sk_buff *skb = precv_frame->pkt;
618 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
619
620 if (ptable->func) {
621
622
623 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&&
624 !is_broadcast_ether_addr(hdr->addr1))
625 return;
626
627 ptable->func(padapter, precv_frame);
628 }
629}
630
631void mgt_dispatcher23a(struct rtw_adapter *padapter,
632 struct recv_frame *precv_frame)
633{
634 struct mlme_handler *ptable;
635#ifdef CONFIG_8723AU_AP_MODE
636 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
637#endif
638 struct sk_buff *skb = precv_frame->pkt;
639 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
640 struct sta_info *psta;
641 u16 stype;
642 int index;
643
644 if (!ieee80211_is_mgmt(mgmt->frame_control))
645 return;
646
647
648
649 if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) &&
650 !is_broadcast_ether_addr(mgmt->da))
651 return;
652
653 ptable = mlme_sta_tbl;
654
655 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
656 index = stype >> 4;
657
658 if (index > 13) {
659 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
660 "Currently we do not support reserved sub-fr-type =%d\n",
661 index);
662 return;
663 }
664 ptable += index;
665
666 psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa);
667
668 if (psta) {
669 if (ieee80211_has_retry(mgmt->frame_control)) {
670 if (precv_frame->attrib.seq_num ==
671 psta->RxMgmtFrameSeqNum) {
672
673 DBG_8723A("Drop duplicate management frame "
674 "with seq_num = %d.\n",
675 precv_frame->attrib.seq_num);
676 return;
677 }
678 }
679 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
680 }
681
682#ifdef CONFIG_8723AU_AP_MODE
683 switch (stype) {
684 case IEEE80211_STYPE_AUTH:
685 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
686 ptable->func = &OnAuth23a;
687 else
688 ptable->func = &OnAuth23aClient23a;
689
690 case IEEE80211_STYPE_ASSOC_REQ:
691 case IEEE80211_STYPE_REASSOC_REQ:
692 _mgt_dispatcher23a(padapter, ptable, precv_frame);
693 break;
694 case IEEE80211_STYPE_PROBE_REQ:
695 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
696 _mgt_dispatcher23a(padapter, ptable, precv_frame);
697 else
698 _mgt_dispatcher23a(padapter, ptable, precv_frame);
699 break;
700 case IEEE80211_STYPE_BEACON:
701 _mgt_dispatcher23a(padapter, ptable, precv_frame);
702 break;
703 case IEEE80211_STYPE_ACTION:
704
705 _mgt_dispatcher23a(padapter, ptable, precv_frame);
706 break;
707 default:
708 _mgt_dispatcher23a(padapter, ptable, precv_frame);
709 break;
710 }
711#else
712 _mgt_dispatcher23a(padapter, ptable, precv_frame);
713#endif
714}
715
716
717
718
719
720
721
722static int
723OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
724{
725 const u8 *ie;
726 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
727 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
728 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
729 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
730 struct sk_buff *skb = precv_frame->pkt;
731 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
732 int len = skb->len;
733
734 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
735 return _SUCCESS;
736
737 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
738 !check_fwstate(pmlmepriv,
739 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
740 return _SUCCESS;
741
742 if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) {
743 printk(KERN_WARNING "%s: Received non probe request frame\n",
744 __func__);
745 return _FAIL;
746 }
747
748 len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
749
750 ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len);
751
752
753 if (!ie)
754 goto out;
755
756 if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) ||
757 (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) {
758 return _SUCCESS;
759 }
760
761 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
762 pmlmepriv->cur_network.join_res)
763 issue_probersp(padapter, mgmt->sa, false);
764
765out:
766 return _SUCCESS;
767}
768
769static int
770OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
771{
772 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
773
774 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
775 report_survey_event23a(padapter, precv_frame);
776 return _SUCCESS;
777 }
778
779 return _SUCCESS;
780}
781
782static int
783OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
784{
785 int cam_idx;
786 struct sta_info *psta;
787 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
788 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
789 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
790 struct sta_priv *pstapriv = &padapter->stapriv;
791 struct sk_buff *skb = precv_frame->pkt;
792 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
793 int pkt_len = skb->len;
794 struct wlan_bssid_ex *pbss;
795 int ret = _SUCCESS;
796 u8 *p, *pie;
797 int pie_len;
798 u32 ielen = 0;
799
800 pie = mgmt->u.beacon.variable;
801 pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
802 p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len);
803 if (p && ielen > 0) {
804 if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) {
805
806
807
808
809 DBG_8723A("[WIFIDBG] Error in ESR IE is detected in "
810 "Beacon of BSSID: %pM. Fix the length of "
811 "ESR IE to avoid failed Beacon parsing.\n",
812 mgmt->bssid);
813 p[1] = ielen - 1;
814 }
815 }
816
817 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
818 report_survey_event23a(padapter, precv_frame);
819 return _SUCCESS;
820 }
821
822 if (!ether_addr_equal(mgmt->bssid,
823 get_my_bssid23a(&pmlmeinfo->network)))
824 goto out;
825
826 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
827
828
829 pbss = collect_bss_info(padapter, precv_frame);
830 if (pbss) {
831 update_network23a(&pmlmepriv->cur_network.network, pbss,
832 padapter, true);
833 rtw_get_bcn_info23a(&pmlmepriv->cur_network);
834 kfree(pbss);
835 }
836
837
838 pmlmeinfo->assoc_AP_vendor =
839 check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len -
840 offsetof(struct ieee80211_mgmt, u));
841
842
843 rtw_update_TSF(pmlmeext, mgmt);
844
845
846 start_clnt_auth(padapter);
847
848 return _SUCCESS;
849 }
850
851 if (((pmlmeinfo->state & 0x03) == MSR_AP) &&
852 (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
853 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
854 if (psta) {
855 ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len);
856 if (ret != _SUCCESS) {
857 DBG_8723A_LEVEL(_drv_always_, "ap has changed, "
858 "disconnect now\n");
859 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
860 return _SUCCESS;
861 }
862
863
864
865 if ((sta_rx_pkts(psta) & 0xf) == 0) {
866
867 update_beacon23a_info(padapter, mgmt,
868 pkt_len, psta);
869 }
870 }
871 } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
872 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
873 if (psta) {
874
875
876
877 if ((sta_rx_pkts(psta) & 0xf) == 0) {
878
879 update_beacon23a_info(padapter, mgmt,
880 pkt_len, psta);
881 }
882 } else {
883
884 cam_idx = allocate_fw_sta_entry23a(padapter);
885 if (cam_idx == NUM_STA)
886 goto out;
887
888
889 if (update_sta_support_rate23a(padapter, pie, pie_len,
890 cam_idx) == _FAIL) {
891 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
892 goto out;
893 }
894
895
896 rtw_update_TSF(pmlmeext, mgmt);
897
898
899 report_add_sta_event23a(padapter, mgmt->sa,
900 cam_idx);
901 }
902 }
903
904out:
905
906 return _SUCCESS;
907}
908
909#ifdef CONFIG_8723AU_AP_MODE
910static int
911OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
912{
913 static struct sta_info stat;
914 struct sta_info *pstat = NULL;
915 struct sta_priv *pstapriv = &padapter->stapriv;
916 struct security_priv *psecuritypriv = &padapter->securitypriv;
917 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
918 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
919 struct sk_buff *skb = precv_frame->pkt;
920 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
921 u8 *pframe;
922 const u8 *p;
923 unsigned char *sa;
924 u16 auth_mode, seq, algorithm;
925 int status, len = skb->len;
926
927 if ((pmlmeinfo->state & 0x03) != MSR_AP)
928 return _FAIL;
929
930 DBG_8723A("+OnAuth23a\n");
931
932 sa = mgmt->sa;
933
934 auth_mode = psecuritypriv->dot11AuthAlgrthm;
935
936 pframe = mgmt->u.auth.variable;
937 len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable);
938
939 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
940 algorithm = le16_to_cpu(mgmt->u.auth.auth_alg);
941
942 DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
943
944 if (auth_mode == 2 &&
945 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 &&
946 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104)
947 auth_mode = 0;
948
949
950
951 if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) ||
952 (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) {
953 DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib "
954 "=%d] %02X%02X%02X%02X%02X%02X\n",
955 algorithm, auth_mode,
956 sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
957
958 status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
959
960 goto auth_fail;
961 }
962
963 if (rtw_access_ctrl23a(padapter, sa) == false) {
964 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
965 goto auth_fail;
966 }
967
968 pstat = rtw_get_stainfo23a(pstapriv, sa);
969 if (!pstat) {
970
971 DBG_8723A("going to alloc stainfo for sa =%pM\n", sa);
972 pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC);
973 if (!pstat) {
974 DBG_8723A(" Exceed the upper limit of supported "
975 "clients...\n");
976 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
977 goto auth_fail;
978 }
979
980 pstat->state = WIFI_FW_AUTH_NULL;
981 pstat->auth_seq = 0;
982
983
984
985 } else {
986 spin_lock_bh(&pstapriv->asoc_list_lock);
987 if (!list_empty(&pstat->asoc_list)) {
988 list_del_init(&pstat->asoc_list);
989 pstapriv->asoc_list_cnt--;
990 if (pstat->expire_to > 0) {
991
992 }
993 }
994 spin_unlock_bh(&pstapriv->asoc_list_lock);
995
996 if (seq == 1) {
997
998 }
999 }
1000
1001 spin_lock_bh(&pstapriv->auth_list_lock);
1002 if (list_empty(&pstat->auth_list)) {
1003 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
1004 pstapriv->auth_list_cnt++;
1005 }
1006 spin_unlock_bh(&pstapriv->auth_list_lock);
1007
1008 if (pstat->auth_seq == 0)
1009 pstat->expire_to = pstapriv->auth_to;
1010
1011 if ((pstat->auth_seq + 1) != seq) {
1012 DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, "
1013 "exp_seq =%d]!\n", seq, pstat->auth_seq+1);
1014 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1015 goto auth_fail;
1016 }
1017
1018 if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) {
1019 if (seq == 1) {
1020 pstat->state &= ~WIFI_FW_AUTH_NULL;
1021 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1022 pstat->expire_to = pstapriv->assoc_to;
1023 pstat->authalg = algorithm;
1024 } else {
1025 DBG_8723A("(2)auth rejected because out of seq "
1026 "[rx_seq =%d, exp_seq =%d]!\n",
1027 seq, pstat->auth_seq+1);
1028 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1029 goto auth_fail;
1030 }
1031 } else {
1032 if (seq == 1) {
1033
1034 pstat->state &= ~WIFI_FW_AUTH_NULL;
1035 pstat->state |= WIFI_FW_AUTH_STATE;
1036 pstat->authalg = algorithm;
1037 pstat->auth_seq = 2;
1038 } else if (seq == 3) {
1039
1040 DBG_8723A("checking for challenging txt...\n");
1041
1042 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len);
1043 if (!p || p[1] <= 0) {
1044 DBG_8723A("auth rejected because challenge "
1045 "failure!(1)\n");
1046 status = WLAN_STATUS_CHALLENGE_FAIL;
1047 goto auth_fail;
1048 }
1049
1050 if (!memcmp(p + 2, pstat->chg_txt, 128)) {
1051 pstat->state &= ~WIFI_FW_AUTH_STATE;
1052 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1053
1054 pstat->expire_to = pstapriv->assoc_to;
1055 } else {
1056 DBG_8723A("auth rejected because challenge "
1057 "failure!\n");
1058 status = WLAN_STATUS_CHALLENGE_FAIL;
1059 goto auth_fail;
1060 }
1061 } else {
1062 DBG_8723A("(3)auth rejected because out of seq "
1063 "[rx_seq =%d, exp_seq =%d]!\n",
1064 seq, pstat->auth_seq+1);
1065 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1066 goto auth_fail;
1067 }
1068 }
1069
1070
1071 pstat->auth_seq = seq + 1;
1072
1073 issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS);
1074
1075 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1076 pstat->auth_seq = 0;
1077
1078 return _SUCCESS;
1079
1080auth_fail:
1081
1082 if (pstat)
1083 rtw_free_stainfo23a(padapter, pstat);
1084
1085 pstat = &stat;
1086 memset((char *)pstat, '\0', sizeof(stat));
1087 pstat->auth_seq = 2;
1088 ether_addr_copy(pstat->hwaddr, sa);
1089
1090 issue_auth(padapter, pstat, (unsigned short)status);
1091
1092 return _FAIL;
1093}
1094#endif
1095
1096static int
1097OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1098{
1099 unsigned int seq, status, algthm;
1100 unsigned int go2asoc = 0;
1101 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1102 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1103 struct sk_buff *skb = precv_frame->pkt;
1104 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1105 const u8 *p;
1106 u8 *pie;
1107 int plen = skb->len;
1108
1109 DBG_8723A("%s\n", __func__);
1110
1111
1112 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
1113 return _SUCCESS;
1114
1115 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1116 return _SUCCESS;
1117
1118 pie = mgmt->u.auth.variable;
1119 plen -= offsetof(struct ieee80211_mgmt, u.auth.variable);
1120
1121 algthm = le16_to_cpu(mgmt->u.auth.auth_alg);
1122 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
1123 status = le16_to_cpu(mgmt->u.auth.status_code);
1124
1125 if (status) {
1126 DBG_8723A("clnt auth fail, status: %d\n", status);
1127
1128 if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
1129 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1130 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1131 else
1132 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1133
1134 }
1135
1136 set_link_timer(pmlmeext, 1);
1137 goto authclnt_fail;
1138 }
1139
1140 if (seq == 2) {
1141 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1142
1143 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen);
1144
1145 if (!p) {
1146
1147 goto authclnt_fail;
1148 }
1149
1150 memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]);
1151 pmlmeinfo->auth_seq = 3;
1152 issue_auth(padapter, NULL, 0);
1153 set_link_timer(pmlmeext, REAUTH_TO);
1154
1155 return _SUCCESS;
1156 } else {
1157
1158 go2asoc = 1;
1159 }
1160 } else if (seq == 4) {
1161 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1162 go2asoc = 1;
1163 else
1164 goto authclnt_fail;
1165 } else {
1166
1167
1168
1169 goto authclnt_fail;
1170 }
1171
1172 if (go2asoc) {
1173 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
1174 start_clnt_assoc(padapter);
1175 return _SUCCESS;
1176 }
1177
1178authclnt_fail:
1179
1180
1181
1182 return _FAIL;
1183}
1184
1185#ifdef CONFIG_8723AU_AP_MODE
1186static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen)
1187{
1188 unsigned int oui;
1189
1190
1191
1192
1193 if (elen < 4) {
1194 DBG_8723A("short vendor specific information element "
1195 "ignored (len =%i)\n", elen);
1196 return -EINVAL;
1197 }
1198
1199 oui = RTW_GET_BE24(pos);
1200 switch (oui) {
1201 case WLAN_OUI_MICROSOFT:
1202
1203
1204 switch (pos[3]) {
1205 case WLAN_OUI_TYPE_MICROSOFT_WPA:
1206
1207
1208 break;
1209 case WLAN_OUI_TYPE_MICROSOFT_WMM:
1210 if (elen < 5) {
1211 DBG_8723A("short WME information element "
1212 "ignored (len =%i)\n", elen);
1213 return -EINVAL;
1214 }
1215 switch (pos[4]) {
1216 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
1217 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
1218 break;
1219 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
1220 break;
1221 default:
1222 DBG_8723A("unknown WME information element "
1223 "ignored (subtype =%d len =%i)\n",
1224 pos[4], elen);
1225 return -EINVAL;
1226 }
1227 break;
1228 case WLAN_OUI_TYPE_MICROSOFT_WPS:
1229
1230 break;
1231 default:
1232 DBG_8723A("Unknown Microsoft information element "
1233 "ignored (type =%d len =%i)\n",
1234 pos[3], elen);
1235 return -EINVAL;
1236 }
1237 break;
1238
1239 case OUI_BROADCOM:
1240 switch (pos[3]) {
1241 case VENDOR_HT_CAPAB_OUI_TYPE:
1242 break;
1243 default:
1244 DBG_8723A("Unknown Broadcom information element "
1245 "ignored (type =%d len =%i)\n", pos[3], elen);
1246 return -EINVAL;
1247 }
1248 break;
1249
1250 default:
1251 DBG_8723A("unknown vendor specific information element "
1252 "ignored (vendor OUI %02x:%02x:%02x len =%i)\n",
1253 pos[0], pos[1], pos[2], elen);
1254 return -EINVAL;
1255 }
1256
1257 return 0;
1258}
1259
1260static int rtw_validate_frame_ies(const u8 *start, uint len)
1261{
1262 const u8 *pos = start;
1263 int left = len;
1264 int unknown = 0;
1265
1266 while (left >= 2) {
1267 u8 id, elen;
1268
1269 id = *pos++;
1270 elen = *pos++;
1271 left -= 2;
1272
1273 if (elen > left) {
1274 DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d "
1275 "left =%i)\n", __func__, id, elen, left);
1276 return -EINVAL;
1277 }
1278
1279 switch (id) {
1280 case WLAN_EID_SSID:
1281 case WLAN_EID_SUPP_RATES:
1282 case WLAN_EID_FH_PARAMS:
1283 case WLAN_EID_DS_PARAMS:
1284 case WLAN_EID_CF_PARAMS:
1285 case WLAN_EID_TIM:
1286 case WLAN_EID_IBSS_PARAMS:
1287 case WLAN_EID_CHALLENGE:
1288 case WLAN_EID_ERP_INFO:
1289 case WLAN_EID_EXT_SUPP_RATES:
1290 break;
1291 case WLAN_EID_VENDOR_SPECIFIC:
1292 if (rtw_validate_vendor_specific_ies(pos, elen))
1293 unknown++;
1294 break;
1295 case WLAN_EID_RSN:
1296 case WLAN_EID_PWR_CAPABILITY:
1297 case WLAN_EID_SUPPORTED_CHANNELS:
1298 case WLAN_EID_MOBILITY_DOMAIN:
1299 case WLAN_EID_FAST_BSS_TRANSITION:
1300 case WLAN_EID_TIMEOUT_INTERVAL:
1301 case WLAN_EID_HT_CAPABILITY:
1302 case WLAN_EID_HT_OPERATION:
1303 default:
1304 unknown++;
1305 DBG_8723A("%s IEEE 802.11 ignored unknown element "
1306 "(id =%d elen =%d)\n", __func__, id, elen);
1307 break;
1308 }
1309
1310 left -= elen;
1311 pos += elen;
1312 }
1313
1314 if (left)
1315 return -EINVAL;
1316
1317 return 0;
1318}
1319#endif
1320
1321static int
1322OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1323{
1324#ifdef CONFIG_8723AU_AP_MODE
1325 u16 capab_info, listen_interval;
1326 struct sta_info *pstat;
1327 unsigned char reassoc;
1328 int i, wpa_ie_len, left;
1329 unsigned char supportRate[16];
1330 int supportRateNum;
1331 unsigned short status = WLAN_STATUS_SUCCESS;
1332 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1333 struct security_priv *psecuritypriv = &padapter->securitypriv;
1334 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1335 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1336 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
1337 struct sta_priv *pstapriv = &padapter->stapriv;
1338 struct sk_buff *skb = precv_frame->pkt;
1339 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1340 const u8 *pos, *p, *wpa_ie, *wps_ie;
1341 u8 *pframe = skb->data;
1342 uint pkt_len = skb->len;
1343 int r;
1344
1345 if ((pmlmeinfo->state & 0x03) != MSR_AP)
1346 return _FAIL;
1347
1348 left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
1349 if (ieee80211_is_assoc_req(mgmt->frame_control)) {
1350 reassoc = 0;
1351 pos = mgmt->u.assoc_req.variable;
1352 left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
1353 } else {
1354 reassoc = 1;
1355 pos = mgmt->u.reassoc_req.variable;
1356 left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable);
1357 }
1358
1359 if (left < 0) {
1360 DBG_8723A("handle_assoc(reassoc =%d) - too short payload "
1361 "(len =%lu)\n", reassoc, (unsigned long)pkt_len);
1362 return _FAIL;
1363 }
1364
1365 pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1366 if (!pstat) {
1367 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1368 goto asoc_class2_error;
1369 }
1370
1371
1372
1373 capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info);
1374 listen_interval =
1375 get_unaligned_le16(&mgmt->u.assoc_req.listen_interval);
1376
1377 DBG_8723A("%s\n", __func__);
1378
1379
1380 if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) {
1381 if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) {
1382 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1383 goto asoc_class2_error;
1384 } else {
1385 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1386 pstat->state |= WIFI_FW_ASSOC_STATE;
1387 }
1388 } else {
1389 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1390 pstat->state |= WIFI_FW_ASSOC_STATE;
1391 }
1392
1393 pstat->capability = capab_info;
1394
1395
1396
1397 if (rtw_validate_frame_ies(pos, left)) {
1398 DBG_8723A("STA %pM sent invalid association request\n",
1399 pstat->hwaddr);
1400 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1401 goto OnAssocReq23aFail;
1402 }
1403
1404
1405
1406 p = cfg80211_find_ie(WLAN_EID_SSID, pos, left);
1407 if (!p || p[1] == 0) {
1408
1409 DBG_8723A("STA %pM sent invalid association request lacking an SSID\n",
1410 pstat->hwaddr);
1411 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1412 goto OnAssocReq23aFail;
1413 } else {
1414
1415 if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len))
1416 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1417
1418 if (p[1] != cur->Ssid.ssid_len)
1419 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1420 }
1421
1422 if (status != WLAN_STATUS_SUCCESS)
1423 goto OnAssocReq23aFail;
1424
1425
1426 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left);
1427 if (!p) {
1428 DBG_8723A("Rx a sta assoc-req which supported rate is "
1429 "empty!\n");
1430
1431
1432
1433
1434 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1435 goto OnAssocReq23aFail;
1436 } else {
1437 memcpy(supportRate, p + 2, p[1]);
1438 supportRateNum = p[1];
1439
1440 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left);
1441 if (p) {
1442 if (supportRateNum <= sizeof(supportRate)) {
1443 memcpy(supportRate+supportRateNum, p + 2, p[1]);
1444 supportRateNum += p[1];
1445 }
1446 }
1447 }
1448
1449
1450
1451
1452
1453 pstat->bssratelen = supportRateNum;
1454 memcpy(pstat->bssrateset, supportRate, supportRateNum);
1455 Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1456
1457
1458 pstat->dot8021xalg = 0;
1459 pstat->wpa_psk = 0;
1460 pstat->wpa_group_cipher = 0;
1461 pstat->wpa2_group_cipher = 0;
1462 pstat->wpa_pairwise_cipher = 0;
1463 pstat->wpa2_pairwise_cipher = 0;
1464 memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1465
1466 wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left);
1467 if (!wpa_ie)
1468 wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1469 WLAN_OUI_TYPE_MICROSOFT_WPA,
1470 pos, left);
1471 if (wpa_ie) {
1472 int group_cipher = 0, pairwise_cipher = 0;
1473
1474 wpa_ie_len = wpa_ie[1];
1475 if (psecuritypriv->wpa_psk & BIT(1)) {
1476 r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2,
1477 &group_cipher,
1478 &pairwise_cipher, NULL);
1479 if (r == _SUCCESS) {
1480 pstat->dot8021xalg = 1;
1481 pstat->wpa_psk |= BIT(1);
1482
1483 pstat->wpa2_group_cipher = group_cipher &
1484 psecuritypriv->wpa2_group_cipher;
1485 pstat->wpa2_pairwise_cipher = pairwise_cipher &
1486 psecuritypriv->wpa2_pairwise_cipher;
1487 } else
1488 status = WLAN_STATUS_INVALID_IE;
1489 } else if (psecuritypriv->wpa_psk & BIT(0)) {
1490 r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2,
1491 &group_cipher, &pairwise_cipher,
1492 NULL);
1493 if (r == _SUCCESS) {
1494 pstat->dot8021xalg = 1;
1495 pstat->wpa_psk |= BIT(0);
1496
1497 pstat->wpa_group_cipher = group_cipher &
1498 psecuritypriv->wpa_group_cipher;
1499 pstat->wpa_pairwise_cipher = pairwise_cipher &
1500 psecuritypriv->wpa_pairwise_cipher;
1501 } else
1502 status = WLAN_STATUS_INVALID_IE;
1503 } else {
1504 wpa_ie = NULL;
1505 wpa_ie_len = 0;
1506 }
1507 if (wpa_ie && status == WLAN_STATUS_SUCCESS) {
1508 if (!pstat->wpa_group_cipher)
1509 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1510
1511 if (!pstat->wpa_pairwise_cipher)
1512 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1513 }
1514 }
1515
1516 if (status != WLAN_STATUS_SUCCESS)
1517 goto OnAssocReq23aFail;
1518
1519 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1520
1521 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1522 WLAN_OUI_TYPE_MICROSOFT_WPS,
1523 pos, left);
1524
1525 if (!wpa_ie) {
1526 if (wps_ie) {
1527 DBG_8723A("STA included WPS IE in (Re)Association "
1528 "Request - assume WPS is used\n");
1529 pstat->flags |= WLAN_STA_WPS;
1530 } else {
1531 DBG_8723A("STA did not include WPA/RSN IE in (Re)"
1532 "Association Request - possible WPS use\n");
1533 pstat->flags |= WLAN_STA_MAYBE_WPS;
1534 }
1535 } else {
1536 int copy_len;
1537
1538 if (psecuritypriv->wpa_psk == 0) {
1539 DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
1540 pstat->hwaddr);
1541
1542 status = WLAN_STATUS_INVALID_IE;
1543
1544 goto OnAssocReq23aFail;
1545 }
1546
1547 if (wps_ie) {
1548 DBG_8723A("STA included WPS IE in (Re)Association "
1549 "Request - WPS is used\n");
1550 pstat->flags |= WLAN_STA_WPS;
1551 copy_len = 0;
1552 } else {
1553 copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ?
1554 sizeof(pstat->wpa_ie) : (wpa_ie_len + 2);
1555 }
1556
1557 if (copy_len > 0)
1558 memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
1559 }
1560
1561
1562 pstat->flags &= ~WLAN_STA_WME;
1563 pstat->qos_option = 0;
1564 pstat->qos_info = 0;
1565 pstat->has_legacy_ac = true;
1566 pstat->uapsd_vo = 0;
1567 pstat->uapsd_vi = 0;
1568 pstat->uapsd_be = 0;
1569 pstat->uapsd_bk = 0;
1570 if (pmlmepriv->qos_option) {
1571 const u8 *end = pos + left;
1572
1573 p = pos;
1574
1575 for (;;) {
1576 left = end - p;
1577 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1578 WLAN_OUI_TYPE_MICROSOFT_WMM,
1579 p, left);
1580 if (p) {
1581 pstat->flags |= WLAN_STA_WME;
1582
1583 pstat->qos_option = 1;
1584 pstat->qos_info = *(p + 8);
1585
1586 pstat->max_sp_len =
1587 (pstat->qos_info >> 5) & 0x3;
1588
1589 if ((pstat->qos_info & 0xf) != 0xf)
1590 pstat->has_legacy_ac = true;
1591 else
1592 pstat->has_legacy_ac = false;
1593
1594 if (pstat->qos_info & 0xf) {
1595 if (pstat->qos_info & BIT(0))
1596 pstat->uapsd_vo = BIT(0)|BIT(1);
1597 else
1598 pstat->uapsd_vo = 0;
1599
1600 if (pstat->qos_info & BIT(1))
1601 pstat->uapsd_vi = BIT(0)|BIT(1);
1602 else
1603 pstat->uapsd_vi = 0;
1604
1605 if (pstat->qos_info & BIT(2))
1606 pstat->uapsd_bk = BIT(0)|BIT(1);
1607 else
1608 pstat->uapsd_bk = 0;
1609
1610 if (pstat->qos_info & BIT(3))
1611 pstat->uapsd_be = BIT(0)|BIT(1);
1612 else
1613 pstat->uapsd_be = 0;
1614
1615 break;
1616 }
1617 } else {
1618 break;
1619 }
1620 p = p + p[1] + 2;
1621 }
1622 }
1623
1624
1625 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1626 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left);
1627
1628 if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) {
1629 pstat->flags |= WLAN_STA_HT;
1630
1631 pstat->flags |= WLAN_STA_WME;
1632
1633 memcpy(&pstat->htpriv.ht_cap, p + 2,
1634 sizeof(struct ieee80211_ht_cap));
1635 } else
1636 pstat->flags &= ~WLAN_STA_HT;
1637
1638 if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){
1639 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1640 goto OnAssocReq23aFail;
1641 }
1642
1643 if (pstat->flags & WLAN_STA_HT &&
1644 (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP ||
1645 pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
1646 DBG_8723A("HT: %pM tried to use TKIP with HT association\n",
1647 pstat->hwaddr);
1648
1649
1650
1651 }
1652
1653 pstat->flags |= WLAN_STA_NONERP;
1654 for (i = 0; i < pstat->bssratelen; i++) {
1655 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1656 pstat->flags &= ~WLAN_STA_NONERP;
1657 break;
1658 }
1659 }
1660
1661 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1662 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1663 else
1664 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1665
1666 if (status != WLAN_STATUS_SUCCESS)
1667 goto OnAssocReq23aFail;
1668
1669
1670
1671
1672
1673
1674
1675
1676 if (pstat->aid > 0) {
1677 DBG_8723A(" old AID %d\n", pstat->aid);
1678 } else {
1679 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1680 if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1681 break;
1682
1683 if (pstat->aid > NUM_STA)
1684 pstat->aid = NUM_STA;
1685 if (pstat->aid > pstapriv->max_num_sta) {
1686
1687 pstat->aid = 0;
1688
1689 DBG_8723A(" no room for more AIDs\n");
1690
1691 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1692
1693 goto OnAssocReq23aFail;
1694 } else {
1695 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1696 DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
1697 }
1698 }
1699
1700 pstat->state &= ~WIFI_FW_ASSOC_STATE;
1701 pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1702
1703 spin_lock_bh(&pstapriv->auth_list_lock);
1704 if (!list_empty(&pstat->auth_list)) {
1705 list_del_init(&pstat->auth_list);
1706 pstapriv->auth_list_cnt--;
1707 }
1708 spin_unlock_bh(&pstapriv->auth_list_lock);
1709
1710 spin_lock_bh(&pstapriv->asoc_list_lock);
1711 if (list_empty(&pstat->asoc_list)) {
1712 pstat->expire_to = pstapriv->expire_to;
1713 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1714 pstapriv->asoc_list_cnt++;
1715 }
1716 spin_unlock_bh(&pstapriv->asoc_list_lock);
1717
1718
1719 if (pstat && pstat->state & WIFI_FW_ASSOC_SUCCESS &&
1720 status == WLAN_STATUS_SUCCESS) {
1721#ifdef CONFIG_8723AU_AP_MODE
1722
1723 bss_cap_update_on_sta_join23a(padapter, pstat);
1724 sta_info_update23a(padapter, pstat);
1725
1726
1727 if (ieee80211_is_assoc_req(mgmt->frame_control))
1728 issue_assocrsp(padapter, status, pstat,
1729 IEEE80211_STYPE_ASSOC_RESP);
1730 else
1731 issue_assocrsp(padapter, status, pstat,
1732 IEEE80211_STYPE_REASSOC_RESP);
1733
1734
1735 DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
1736 rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1737
1738
1739 report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid);
1740#endif
1741 }
1742
1743 return _SUCCESS;
1744
1745asoc_class2_error:
1746
1747#ifdef CONFIG_8723AU_AP_MODE
1748 issue_deauth23a(padapter, mgmt->sa, status);
1749#endif
1750 return _FAIL;
1751
1752OnAssocReq23aFail:
1753
1754#ifdef CONFIG_8723AU_AP_MODE
1755 pstat->aid = 0;
1756 if (ieee80211_is_assoc_req(mgmt->frame_control))
1757 issue_assocrsp(padapter, status, pstat,
1758 IEEE80211_STYPE_ASSOC_RESP);
1759 else
1760 issue_assocrsp(padapter, status, pstat,
1761 IEEE80211_STYPE_REASSOC_RESP);
1762#endif
1763
1764#endif
1765
1766 return _FAIL;
1767}
1768
1769static int
1770OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1771{
1772 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1773 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1774 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1775 struct sk_buff *skb = precv_frame->pkt;
1776 struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
1777 int res;
1778 unsigned short status;
1779 const u8 *p, *pie;
1780 u8 *pframe = skb->data;
1781 int pkt_len = skb->len;
1782 int pielen;
1783
1784 DBG_8723A("%s\n", __func__);
1785
1786
1787 if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da))
1788 return _SUCCESS;
1789
1790 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1791 return _SUCCESS;
1792
1793 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1794 return _SUCCESS;
1795
1796 del_timer_sync(&pmlmeext->link_timer);
1797
1798
1799 status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
1800 if (status > 0) {
1801 DBG_8723A("assoc reject, status code: %d\n", status);
1802 pmlmeinfo->state = MSR_NOLINK;
1803 res = -4;
1804 goto report_assoc_result;
1805 }
1806
1807
1808 pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info);
1809
1810
1811 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
1812
1813
1814 res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
1815
1816 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1817 pielen = pkt_len -
1818 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1819
1820 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
1821 pmgmt->u.assoc_resp.variable, pielen);
1822 if (p && p[1])
1823 HT_caps_handler23a(padapter, p);
1824
1825 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
1826 pmgmt->u.assoc_resp.variable, pielen);
1827 if (p && p[1])
1828 HT_info_handler23a(padapter, p);
1829
1830 p = cfg80211_find_ie(WLAN_EID_ERP_INFO,
1831 pmgmt->u.assoc_resp.variable, pielen);
1832 if (p && p[1])
1833 ERP_IE_handler23a(padapter, p);
1834
1835 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1836 while (true) {
1837 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1838 WLAN_OUI_TYPE_MICROSOFT_WMM,
1839 pie, pframe + pkt_len - pie);
1840 if (!p)
1841 break;
1842
1843 pie = p + p[1] + 2;
1844
1845 if (p[1] <= 4)
1846 continue;
1847
1848 if (p[6] == 1)
1849 break;
1850 }
1851
1852 if (p && p[1])
1853 WMM_param_handler23a(padapter, p);
1854
1855 pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
1856 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1857
1858
1859 UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates);
1860
1861report_assoc_result:
1862 pmlmepriv->assoc_rsp_len = 0;
1863 if (res > 0) {
1864 kfree(pmlmepriv->assoc_rsp);
1865 pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC);
1866 if (pmlmepriv->assoc_rsp) {
1867 memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len);
1868 pmlmepriv->assoc_rsp_len = pkt_len;
1869 }
1870 } else
1871 kfree(pmlmepriv->assoc_rsp);
1872
1873 report_join_res23a(padapter, res);
1874
1875 return _SUCCESS;
1876}
1877
1878static int
1879OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1880{
1881 unsigned short reason;
1882 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1883 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1884 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1885 struct sk_buff *skb = precv_frame->pkt;
1886 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1887
1888 if (!ether_addr_equal(mgmt->bssid,
1889 get_my_bssid23a(&pmlmeinfo->network)))
1890 return _SUCCESS;
1891
1892 reason = le16_to_cpu(mgmt->u.deauth.reason_code);
1893
1894 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1895
1896#ifdef CONFIG_8723AU_AP_MODE
1897 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1898 struct sta_info *psta;
1899 struct sta_priv *pstapriv = &padapter->stapriv;
1900
1901 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
1902 "sta:%pM\n", reason, mgmt->sa);
1903
1904 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1905 if (psta) {
1906 u8 updated = 0;
1907
1908 spin_lock_bh(&pstapriv->asoc_list_lock);
1909 if (!list_empty(&psta->asoc_list)) {
1910 list_del_init(&psta->asoc_list);
1911 pstapriv->asoc_list_cnt--;
1912 updated = ap_free_sta23a(padapter, psta,
1913 false, reason);
1914 }
1915 spin_unlock_bh(&pstapriv->asoc_list_lock);
1916
1917 associated_clients_update23a(padapter, updated);
1918 }
1919
1920 return _SUCCESS;
1921 } else
1922#endif
1923 {
1924 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
1925 "sta:%pM\n", reason, mgmt->bssid);
1926
1927 receive_disconnect23a(padapter, mgmt->bssid, reason);
1928 }
1929 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1930
1931 return _SUCCESS;
1932}
1933
1934static int
1935OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1936{
1937 unsigned short reason;
1938 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1939 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1940 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1941 struct sk_buff *skb = precv_frame->pkt;
1942 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1943
1944 if (!ether_addr_equal(mgmt->bssid,
1945 get_my_bssid23a(&pmlmeinfo->network)))
1946 return _SUCCESS;
1947
1948 reason = le16_to_cpu(mgmt->u.disassoc.reason_code);
1949
1950 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1951
1952#ifdef CONFIG_8723AU_AP_MODE
1953 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1954 struct sta_info *psta;
1955 struct sta_priv *pstapriv = &padapter->stapriv;
1956
1957 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
1958 " sta:%pM\n", reason, mgmt->sa);
1959
1960 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1961 if (psta) {
1962 u8 updated = 0;
1963
1964 spin_lock_bh(&pstapriv->asoc_list_lock);
1965 if (!list_empty(&psta->asoc_list)) {
1966 list_del_init(&psta->asoc_list);
1967 pstapriv->asoc_list_cnt--;
1968 updated = ap_free_sta23a(padapter, psta,
1969 false, reason);
1970 }
1971 spin_unlock_bh(&pstapriv->asoc_list_lock);
1972
1973 associated_clients_update23a(padapter, updated);
1974 }
1975
1976 return _SUCCESS;
1977 } else
1978#endif
1979 {
1980 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
1981 "code(%d) sta:%pM\n", reason, mgmt->bssid);
1982
1983 receive_disconnect23a(padapter, mgmt->bssid, reason);
1984 }
1985 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1986 return _SUCCESS;
1987}
1988
1989static int
1990OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1991{
1992 DBG_8723A("%s\n", __func__);
1993 return _SUCCESS;
1994}
1995
1996static int
1997on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1998{
1999 return _FAIL;
2000}
2001
2002static int
2003OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2004{
2005 return _SUCCESS;
2006}
2007
2008static int
2009OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2010{
2011 return _SUCCESS;
2012}
2013
2014static int OnAction23a_back23a(struct rtw_adapter *padapter,
2015 struct recv_frame *precv_frame)
2016{
2017 u8 *addr;
2018 struct sta_info *psta = NULL;
2019 struct recv_reorder_ctrl *preorder_ctrl;
2020 unsigned char category, action;
2021 unsigned short tid, status, capab, params, reason_code = 0;
2022 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2023 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2024 struct sk_buff *skb = precv_frame->pkt;
2025 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2026 struct sta_priv *pstapriv = &padapter->stapriv;
2027
2028
2029 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
2030 return _SUCCESS;
2031
2032 DBG_8723A("%s\n", __func__);
2033
2034 if ((pmlmeinfo->state&0x03) != MSR_AP)
2035 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2036 return _SUCCESS;
2037
2038 addr = mgmt->sa;
2039 psta = rtw_get_stainfo23a(pstapriv, addr);
2040
2041 if (!psta)
2042 return _SUCCESS;
2043
2044 category = mgmt->u.action.category;
2045 if (category == WLAN_CATEGORY_BACK) {
2046 if (!pmlmeinfo->HT_enable)
2047 return _SUCCESS;
2048
2049
2050 action = mgmt->u.action.u.wme_action.action_code;
2051 DBG_8723A("%s, action =%d\n", __func__, action);
2052 switch (action) {
2053 case WLAN_ACTION_ADDBA_REQ:
2054 memcpy(&pmlmeinfo->ADDBA_req,
2055 &mgmt->u.action.u.addba_req.dialog_token,
2056 sizeof(struct ADDBA_request));
2057 process_addba_req23a(padapter,
2058 (u8 *)&pmlmeinfo->ADDBA_req, addr);
2059 if (pmlmeinfo->bAcceptAddbaReq == true)
2060 issue_action_BA23a(padapter, addr,
2061 WLAN_ACTION_ADDBA_RESP, 0);
2062 else {
2063
2064 issue_action_BA23a(padapter, addr,
2065 WLAN_ACTION_ADDBA_RESP, 37);
2066 }
2067 break;
2068 case WLAN_ACTION_ADDBA_RESP:
2069 status = get_unaligned_le16(
2070 &mgmt->u.action.u.addba_resp.status);
2071 capab = get_unaligned_le16(
2072 &mgmt->u.action.u.addba_resp.capab);
2073 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
2074 if (status == 0) {
2075 DBG_8723A("agg_enable for TID =%d\n", tid);
2076 psta->htpriv.agg_enable_bitmap |= BIT(tid);
2077 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2078 } else
2079 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2080 break;
2081
2082 case WLAN_ACTION_DELBA:
2083 params = get_unaligned_le16(
2084 &mgmt->u.action.u.delba.params);
2085 tid = params >> 12;
2086
2087 if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
2088 preorder_ctrl = &psta->recvreorder_ctrl[tid];
2089 preorder_ctrl->enable = false;
2090 preorder_ctrl->indicate_seq = 0xffff;
2091 } else {
2092 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2093 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2094 }
2095 reason_code = get_unaligned_le16(
2096 &mgmt->u.action.u.delba.reason_code);
2097
2098
2099 break;
2100 default:
2101 break;
2102 }
2103 }
2104 return _SUCCESS;
2105}
2106
2107static int on_action_public23a(struct rtw_adapter *padapter,
2108 struct recv_frame *precv_frame)
2109{
2110 struct sk_buff *skb = precv_frame->pkt;
2111 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2112 u8 *pframe = skb->data;
2113 int freq, channel;
2114
2115
2116 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
2117 return _FAIL;
2118
2119 channel = rtw_get_oper_ch23a(padapter);
2120
2121 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2122 freq = ieee80211_channel_to_frequency(channel,
2123 IEEE80211_BAND_2GHZ);
2124 else
2125 freq = ieee80211_channel_to_frequency(channel,
2126 IEEE80211_BAND_5GHZ);
2127
2128 if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
2129 skb->len, 0))
2130 return _SUCCESS;
2131
2132 return _FAIL;
2133}
2134
2135static int
2136OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2137{
2138 return _SUCCESS;
2139}
2140
2141static int
2142OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2143{
2144 return _SUCCESS;
2145}
2146
2147static int
2148OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2149{
2150 return _SUCCESS;
2151}
2152
2153static int
2154OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2155{
2156 int i;
2157 u8 category;
2158 struct action_handler *ptable;
2159 struct sk_buff *skb = precv_frame->pkt;
2160 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2161
2162 category = mgmt->u.action.category;
2163
2164 for (i = 0;
2165 i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) {
2166 ptable = &OnAction23a_tbl[i];
2167
2168 if (category == ptable->num)
2169 ptable->func(padapter, precv_frame);
2170 }
2171
2172 return _SUCCESS;
2173}
2174
2175static int DoReserved23a(struct rtw_adapter *padapter,
2176 struct recv_frame *precv_frame)
2177{
2178 return _SUCCESS;
2179}
2180
2181struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
2182{
2183 struct xmit_frame *pmgntframe;
2184 struct xmit_buf *pxmitbuf;
2185
2186 pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
2187
2188 if (!pmgntframe) {
2189 DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__,
2190 pxmitpriv->adapter->pnetdev->name);
2191 goto exit;
2192 }
2193
2194 pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
2195 if (!pxmitbuf) {
2196 DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__,
2197 pxmitpriv->adapter->pnetdev->name);
2198 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
2199 pmgntframe = NULL;
2200 goto exit;
2201 }
2202
2203 pmgntframe->frame_tag = MGNT_FRAMETAG;
2204 pmgntframe->pxmitbuf = pxmitbuf;
2205 pmgntframe->buf_addr = pxmitbuf->pbuf;
2206 pxmitbuf->priv_data = pmgntframe;
2207
2208exit:
2209 return pmgntframe;
2210}
2211
2212
2213
2214
2215
2216
2217
2218void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
2219{
2220 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2221
2222 pmlmeext->tx_rate = rate;
2223 DBG_8723A("%s(): rate = %x\n", __func__, rate);
2224}
2225
2226void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
2227 struct pkt_attrib *pattrib)
2228{
2229 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2230
2231 memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
2232
2233 pattrib->hdrlen = 24;
2234 pattrib->nr_frags = 1;
2235 pattrib->priority = 7;
2236 pattrib->mac_id = 0;
2237 pattrib->qsel = 0x12;
2238
2239 pattrib->pktlen = 0;
2240
2241 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
2242 pattrib->raid = 6;
2243 else
2244 pattrib->raid = 5;
2245
2246 pattrib->encrypt = 0;
2247 pattrib->bswenc = false;
2248
2249 pattrib->qos_en = false;
2250 pattrib->ht_en = false;
2251 pattrib->bwmode = HT_CHANNEL_WIDTH_20;
2252 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2253 pattrib->sgi = false;
2254
2255 pattrib->seqnum = pmlmeext->mgnt_seq;
2256
2257 pattrib->retry_ctrl = true;
2258}
2259
2260void dump_mgntframe23a(struct rtw_adapter *padapter,
2261 struct xmit_frame *pmgntframe)
2262{
2263 if (padapter->bSurpriseRemoved == true ||
2264 padapter->bDriverStopped == true)
2265 return;
2266
2267 rtl8723au_mgnt_xmit(padapter, pmgntframe);
2268}
2269
2270int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
2271 struct xmit_frame *pmgntframe, int timeout_ms)
2272{
2273 int ret = _FAIL;
2274 unsigned long irqL;
2275 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2276 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2277 struct submit_ctx sctx;
2278
2279 if (padapter->bSurpriseRemoved == true ||
2280 padapter->bDriverStopped == true)
2281 return ret;
2282
2283 rtw_sctx_init23a(&sctx, timeout_ms);
2284 pxmitbuf->sctx = &sctx;
2285
2286 ret = rtl8723au_mgnt_xmit(padapter, pmgntframe);
2287
2288 if (ret == _SUCCESS)
2289 ret = rtw_sctx_wait23a(&sctx);
2290
2291 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2292 pxmitbuf->sctx = NULL;
2293 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2294
2295 return ret;
2296}
2297
2298int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
2299 struct xmit_frame *pmgntframe)
2300{
2301 int ret = _FAIL;
2302 u32 timeout_ms = 500;
2303 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2304
2305 if (padapter->bSurpriseRemoved == true ||
2306 padapter->bDriverStopped == true)
2307 return _FAIL;
2308
2309 mutex_lock(&pxmitpriv->ack_tx_mutex);
2310 pxmitpriv->ack_tx = true;
2311
2312 pmgntframe->ack_report = 1;
2313 if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2314 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
2315
2316 pxmitpriv->ack_tx = false;
2317 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2318
2319 return ret;
2320}
2321
2322static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2323{
2324 u8 *ssid_ie;
2325 int ssid_len_ori;
2326 int len_diff = 0;
2327 u8 *next_ie;
2328 u32 remain_len;
2329
2330 ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
2331
2332
2333
2334
2335 if (ssid_ie && ssid_len_ori > 0) {
2336 switch (hidden_ssid_mode) {
2337 case 1:
2338 next_ie = ssid_ie + 2 + ssid_len_ori;
2339 remain_len = ies_len -(next_ie-ies);
2340
2341 ssid_ie[1] = 0;
2342 memcpy(ssid_ie+2, next_ie, remain_len);
2343 len_diff -= ssid_len_ori;
2344
2345 break;
2346 case 2:
2347 memset(&ssid_ie[2], 0, ssid_len_ori);
2348 break;
2349 default:
2350 break;
2351 }
2352 }
2353
2354 return len_diff;
2355}
2356
2357void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
2358{
2359 struct xmit_frame *pmgntframe;
2360 struct pkt_attrib *pattrib;
2361 unsigned char *pframe;
2362 struct ieee80211_mgmt *mgmt;
2363 unsigned int rate_len;
2364 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2365 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2366 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2367 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2368 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2369 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2370 const u8 *wps_ie;
2371 u8 sr = 0;
2372 int len_diff;
2373
2374
2375
2376 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2377 if (!pmgntframe) {
2378 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2379 return;
2380 }
2381#ifdef CONFIG_8723AU_AP_MODE
2382 spin_lock_bh(&pmlmepriv->bcn_update_lock);
2383#endif
2384
2385
2386 pattrib = &pmgntframe->attrib;
2387 update_mgntframe_attrib23a(padapter, pattrib);
2388 pattrib->qsel = 0x10;
2389
2390 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2391
2392 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2393 mgmt = (struct ieee80211_mgmt *)pframe;
2394
2395 mgmt->frame_control =
2396 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
2397 mgmt->seq_ctrl = 0;
2398
2399 ether_addr_copy(mgmt->da, bc_addr);
2400 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2401 ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
2402
2403
2404
2405 put_unaligned_le16(cur_network->beacon_interval,
2406 &mgmt->u.beacon.beacon_int);
2407
2408 put_unaligned_le16(cur_network->capability,
2409 &mgmt->u.beacon.capab_info);
2410
2411 pframe = mgmt->u.beacon.variable;
2412 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
2413
2414 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2415 u8 *iebuf;
2416 int buflen;
2417
2418 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2419 len_diff = update_hidden_ssid(pframe, cur_network->IELength,
2420 pmlmeinfo->hidden_ssid_mode);
2421 pframe += (cur_network->IELength+len_diff);
2422 pattrib->pktlen += (cur_network->IELength+len_diff);
2423
2424 iebuf = mgmt->u.beacon.variable;
2425 buflen = pattrib->pktlen -
2426 offsetof(struct ieee80211_mgmt, u.beacon.variable);
2427 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2428 WLAN_OUI_TYPE_MICROSOFT_WPS,
2429 iebuf, buflen);
2430
2431 if (wps_ie && wps_ie[1] > 0) {
2432 rtw_get_wps_attr_content23a(wps_ie, wps_ie[1],
2433 WPS_ATTR_SELECTED_REGISTRAR,
2434 (u8 *)&sr);
2435 }
2436 if (sr != 0)
2437 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2438 else
2439 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2440
2441 goto _issue_bcn;
2442 }
2443
2444
2445 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2446 cur_network->Ssid.ssid_len,
2447 cur_network->Ssid.ssid, &pattrib->pktlen);
2448
2449
2450 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2451 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2452 ((rate_len > 8)? 8: rate_len),
2453 cur_network->SupportedRates, &pattrib->pktlen);
2454
2455
2456 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
2457 &cur_network->DSConfig, &pattrib->pktlen);
2458
2459
2460 {
2461 u8 erpinfo = 0;
2462 u32 ATIMWindow;
2463
2464
2465 ATIMWindow = 0;
2466 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2467 (unsigned char *)&ATIMWindow,
2468 &pattrib->pktlen);
2469
2470
2471 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2472 &erpinfo, &pattrib->pktlen);
2473 }
2474
2475
2476 if (rate_len > 8)
2477 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2478 rate_len - 8,
2479 cur_network->SupportedRates + 8,
2480 &pattrib->pktlen);
2481
2482
2483
2484_issue_bcn:
2485
2486#ifdef CONFIG_8723AU_AP_MODE
2487 pmlmepriv->update_bcn = false;
2488
2489 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2490#endif
2491
2492 if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
2493 DBG_8723A("beacon frame too large\n");
2494 return;
2495 }
2496
2497 pattrib->last_txcmdsz = pattrib->pktlen;
2498
2499
2500 if (timeout_ms > 0)
2501 dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
2502 else
2503 dump_mgntframe23a(padapter, pmgntframe);
2504}
2505
2506static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da,
2507 u8 is_valid_p2p_probereq)
2508{
2509 struct xmit_frame *pmgntframe;
2510 struct pkt_attrib *pattrib;
2511 unsigned char *pframe;
2512 struct ieee80211_mgmt *mgmt;
2513 unsigned char *mac, *bssid;
2514 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2515#ifdef CONFIG_8723AU_AP_MODE
2516 const u8 *pwps_ie;
2517 u8 *ssid_ie;
2518 int ssid_ielen;
2519 int ssid_ielen_diff;
2520 u8 buf[MAX_IE_SZ];
2521#endif
2522 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2523 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2524 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2525 unsigned int rate_len;
2526
2527
2528
2529 if (cur_network->IELength > MAX_IE_SZ)
2530 return;
2531
2532 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2533 if (!pmgntframe) {
2534 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2535 return;
2536 }
2537
2538
2539 pattrib = &pmgntframe->attrib;
2540 update_mgntframe_attrib23a(padapter, pattrib);
2541
2542 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2543
2544 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
2545 mgmt = (struct ieee80211_mgmt *)pframe;
2546
2547 mac = myid(&padapter->eeprompriv);
2548 bssid = cur_network->MacAddress;
2549
2550 mgmt->frame_control =
2551 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
2552
2553 ether_addr_copy(mgmt->da, da);
2554 ether_addr_copy(mgmt->sa, mac);
2555 ether_addr_copy(mgmt->bssid, bssid);
2556
2557 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2558 pmlmeext->mgnt_seq++;
2559
2560 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2561
2562
2563 put_unaligned_le16(cur_network->beacon_interval,
2564 &mgmt->u.probe_resp.beacon_int);
2565
2566 put_unaligned_le16(cur_network->capability,
2567 &mgmt->u.probe_resp.capab_info);
2568
2569 pframe = mgmt->u.probe_resp.variable;
2570 pattrib->pktlen =
2571 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
2572
2573
2574
2575#ifdef CONFIG_8723AU_AP_MODE
2576 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2577 pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2578 WLAN_OUI_TYPE_MICROSOFT_WPS,
2579 cur_network->IEs,
2580 cur_network->IELength);
2581
2582 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2583 pframe += cur_network->IELength;
2584 pattrib->pktlen += cur_network->IELength;
2585
2586
2587
2588 ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable,
2589 WLAN_EID_SSID, &ssid_ielen,
2590 pframe - mgmt->u.probe_resp.variable);
2591
2592 ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
2593
2594 if (ssid_ie && cur_network->Ssid.ssid_len) {
2595 uint remainder_ielen;
2596 u8 *remainder_ie;
2597
2598 remainder_ie = ssid_ie + 2;
2599
2600 remainder_ielen = pframe - remainder_ie;
2601
2602 DBG_8723A_LEVEL(_drv_warning_, "%s(%s): "
2603 "remainder_ielen > MAX_IE_SZ\n",
2604 __func__, padapter->pnetdev->name);
2605 if (remainder_ielen > MAX_IE_SZ)
2606 remainder_ielen = MAX_IE_SZ;
2607
2608 memcpy(buf, remainder_ie, remainder_ielen);
2609 memcpy(remainder_ie + ssid_ielen_diff, buf,
2610 remainder_ielen);
2611 *(ssid_ie + 1) = cur_network->Ssid.ssid_len;
2612 memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
2613 cur_network->Ssid.ssid_len);
2614
2615 pframe += ssid_ielen_diff;
2616 pattrib->pktlen += ssid_ielen_diff;
2617 }
2618 } else
2619#endif
2620 {
2621
2622 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2623 cur_network->Ssid.ssid_len,
2624 cur_network->Ssid.ssid,
2625 &pattrib->pktlen);
2626
2627
2628 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2629 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2630 ((rate_len > 8)? 8: rate_len),
2631 cur_network->SupportedRates,
2632 &pattrib->pktlen);
2633
2634
2635 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
2636 (unsigned char *)&cur_network->DSConfig,
2637 &pattrib->pktlen);
2638
2639 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
2640 u8 erpinfo = 0;
2641 u32 ATIMWindow;
2642
2643
2644 ATIMWindow = 0;
2645 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2646 (unsigned char *)&ATIMWindow,
2647 &pattrib->pktlen);
2648
2649
2650 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2651 &erpinfo, &pattrib->pktlen);
2652 }
2653
2654
2655 if (rate_len > 8)
2656 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2657 rate_len - 8,
2658 cur_network->SupportedRates + 8,
2659 &pattrib->pktlen);
2660
2661
2662 }
2663
2664 pattrib->last_txcmdsz = pattrib->pktlen;
2665
2666 dump_mgntframe23a(padapter, pmgntframe);
2667
2668 return;
2669}
2670
2671static int _issue_probereq(struct rtw_adapter *padapter,
2672 struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
2673{
2674 int ret = _FAIL;
2675 struct xmit_frame *pmgntframe;
2676 struct pkt_attrib *pattrib;
2677 unsigned char *pframe;
2678 struct ieee80211_hdr *pwlanhdr;
2679 unsigned char *mac;
2680 unsigned char bssrate[NumRates];
2681 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2682 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2683 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2684 int bssrate_len = 0;
2685 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2686
2687 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2688 "+%s\n", __func__);
2689
2690 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2691 if (!pmgntframe)
2692 goto exit;
2693
2694
2695 pattrib = &pmgntframe->attrib;
2696 update_mgntframe_attrib23a(padapter, pattrib);
2697
2698 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2699
2700 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2701 pwlanhdr = (struct ieee80211_hdr *)pframe;
2702
2703 mac = myid(&padapter->eeprompriv);
2704
2705 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2706 IEEE80211_STYPE_PROBE_REQ);
2707
2708 if (da) {
2709
2710 ether_addr_copy(pwlanhdr->addr1, da);
2711 ether_addr_copy(pwlanhdr->addr3, da);
2712 } else {
2713
2714 ether_addr_copy(pwlanhdr->addr1, bc_addr);
2715 ether_addr_copy(pwlanhdr->addr3, bc_addr);
2716 }
2717
2718 ether_addr_copy(pwlanhdr->addr2, mac);
2719
2720 pwlanhdr->seq_ctrl =
2721 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2722
2723 pmlmeext->mgnt_seq++;
2724
2725 pframe += sizeof (struct ieee80211_hdr_3addr);
2726 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
2727
2728 if (pssid)
2729 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
2730 pssid->ssid, &pattrib->pktlen);
2731 else
2732 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
2733 &pattrib->pktlen);
2734
2735 get_rate_set23a(padapter, bssrate, &bssrate_len);
2736
2737 if (bssrate_len > 8) {
2738 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
2739 bssrate, &pattrib->pktlen);
2740 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2741 (bssrate_len - 8), (bssrate + 8),
2742 &pattrib->pktlen);
2743 } else {
2744 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2745 bssrate_len, bssrate, &pattrib->pktlen);
2746 }
2747
2748
2749 if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
2750 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
2751 pmlmepriv->wps_probe_req_ie_len);
2752 pframe += pmlmepriv->wps_probe_req_ie_len;
2753 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2754 }
2755
2756 pattrib->last_txcmdsz = pattrib->pktlen;
2757
2758 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2759 "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz);
2760
2761 if (wait_ack) {
2762 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
2763 } else {
2764 dump_mgntframe23a(padapter, pmgntframe);
2765 ret = _SUCCESS;
2766 }
2767
2768exit:
2769 return ret;
2770}
2771
2772static inline void issue_probereq(struct rtw_adapter *padapter,
2773 struct cfg80211_ssid *pssid, u8 *da)
2774{
2775 _issue_probereq(padapter, pssid, da, false);
2776}
2777
2778static int issue_probereq_ex(struct rtw_adapter *padapter,
2779 struct cfg80211_ssid *pssid, u8 *da,
2780 int try_cnt, int wait_ms)
2781{
2782 int ret;
2783 int i = 0;
2784 unsigned long start = jiffies;
2785
2786 do {
2787 ret = _issue_probereq(padapter, pssid, da,
2788 wait_ms > 0 ? true : false);
2789
2790 i++;
2791
2792 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2793 break;
2794
2795 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2796 msleep(wait_ms);
2797
2798 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2799
2800 if (ret != _FAIL) {
2801 ret = _SUCCESS;
2802 goto exit;
2803 }
2804
2805 if (try_cnt && wait_ms) {
2806 if (da)
2807 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
2808 __func__, padapter->pnetdev->name,
2809 da, rtw_get_oper_ch23a(padapter),
2810 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2811 jiffies_to_msecs(jiffies - start));
2812 else
2813 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
2814 __func__, padapter->pnetdev->name,
2815 rtw_get_oper_ch23a(padapter),
2816 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2817 jiffies_to_msecs(jiffies - start));
2818 }
2819exit:
2820 return ret;
2821}
2822
2823
2824static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
2825 unsigned short status)
2826{
2827 struct xmit_frame *pmgntframe;
2828 struct pkt_attrib *pattrib;
2829 unsigned char *pframe;
2830 struct ieee80211_mgmt *mgmt;
2831 unsigned int val32;
2832 u16 auth_algo;
2833 int use_shared_key = 0;
2834 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2835 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2836 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2837
2838 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2839 if (!pmgntframe)
2840 return;
2841
2842
2843 pattrib = &pmgntframe->attrib;
2844 update_mgntframe_attrib23a(padapter, pattrib);
2845
2846 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2847
2848 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2849 mgmt = (struct ieee80211_mgmt *)pframe;
2850
2851 mgmt->frame_control =
2852 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
2853 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2854 pmlmeext->mgnt_seq++;
2855
2856 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable);
2857
2858 if (psta) {
2859#ifdef CONFIG_8723AU_AP_MODE
2860 unsigned short val16;
2861
2862 ether_addr_copy(mgmt->da, psta->hwaddr);
2863 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2864 ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv));
2865
2866
2867 val16 = (u16)psta->authalg;
2868
2869 if (status != WLAN_STATUS_SUCCESS)
2870 val16 = 0;
2871
2872 if (val16)
2873 use_shared_key = 1;
2874
2875 mgmt->u.auth.auth_alg = cpu_to_le16(val16);
2876
2877
2878 mgmt->u.auth.auth_transaction =
2879 cpu_to_le16((u16)psta->auth_seq);
2880
2881
2882 mgmt->u.auth.status_code = cpu_to_le16(status);
2883
2884 pframe = mgmt->u.auth.variable;
2885
2886 if ((psta->auth_seq == 2) &&
2887 (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
2888 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2889 psta->chg_txt, &pattrib->pktlen);
2890#endif
2891 } else {
2892 struct ieee80211_mgmt *iv_mgmt;
2893
2894 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
2895 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2896 ether_addr_copy(mgmt->bssid,
2897 get_my_bssid23a(&pmlmeinfo->network));
2898
2899
2900
2901 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
2902 use_shared_key = 1;
2903 auth_algo = WLAN_AUTH_SHARED_KEY;
2904 } else
2905 auth_algo = WLAN_AUTH_OPEN;
2906
2907
2908
2909
2910
2911
2912 if ((pmlmeinfo->auth_seq == 3) &&
2913 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2914 (use_shared_key == 1)) {
2915 u32 *piv = (u32 *)&mgmt->u.auth;
2916
2917 iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4);
2918
2919
2920 val32 = (pmlmeinfo->iv & 0x3fffffff) |
2921 (pmlmeinfo->key_index << 30);
2922 pmlmeinfo->iv++;
2923 put_unaligned_le32(val32, piv);
2924
2925 pattrib->pktlen += 4;
2926
2927 pattrib->iv_len = IEEE80211_WEP_IV_LEN;
2928 } else
2929 iv_mgmt = mgmt;
2930
2931 iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo);
2932
2933
2934 iv_mgmt->u.auth.auth_transaction =
2935 cpu_to_le16(pmlmeinfo->auth_seq);
2936
2937
2938 iv_mgmt->u.auth.status_code = cpu_to_le16(status);
2939
2940 pframe = iv_mgmt->u.auth.variable;
2941
2942
2943 if ((pmlmeinfo->auth_seq == 3) &&
2944 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2945 (use_shared_key == 1)) {
2946 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2947 pmlmeinfo->chg_txt,
2948 &pattrib->pktlen);
2949
2950 mgmt->frame_control |=
2951 cpu_to_le16(IEEE80211_FCTL_PROTECTED);
2952
2953 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2954
2955 pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40;
2956
2957 pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
2958
2959 pattrib->pktlen += pattrib->icv_len;
2960 }
2961 }
2962
2963 pattrib->last_txcmdsz = pattrib->pktlen;
2964
2965 rtw_wep_encrypt23a(padapter, pmgntframe);
2966 DBG_8723A("%s\n", __func__);
2967 dump_mgntframe23a(padapter, pmgntframe);
2968
2969 return;
2970}
2971
2972#ifdef CONFIG_8723AU_AP_MODE
2973static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
2974 struct sta_info *pstat, u16 pkt_type)
2975{
2976 struct xmit_frame *pmgntframe;
2977 struct ieee80211_mgmt *mgmt;
2978 struct pkt_attrib *pattrib;
2979 unsigned char *pframe;
2980 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2981 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2982 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2983 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2984 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
2985 const u8 *p;
2986 u8 *ie = pnetwork->IEs;
2987
2988 DBG_8723A("%s\n", __func__);
2989
2990 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2991 if (!pmgntframe)
2992 return;
2993
2994
2995 pattrib = &pmgntframe->attrib;
2996 update_mgntframe_attrib23a(padapter, pattrib);
2997
2998 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2999
3000 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3001 mgmt = (struct ieee80211_mgmt *)pframe;
3002
3003 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
3004
3005 ether_addr_copy(mgmt->da, pstat->hwaddr);
3006 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3007 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3008
3009 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3010
3011 pmlmeext->mgnt_seq++;
3012
3013 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3014 pattrib->pktlen =
3015 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
3016
3017 mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability);
3018 mgmt->u.assoc_resp.status_code = cpu_to_le16(status);
3019 mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
3020
3021 pframe = mgmt->u.assoc_resp.variable;
3022
3023 if (pstat->bssratelen <= 8) {
3024 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3025 pstat->bssratelen, pstat->bssrateset,
3026 &pattrib->pktlen);
3027 } else {
3028 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3029 pstat->bssrateset, &pattrib->pktlen);
3030 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3031 pstat->bssratelen - 8,
3032 pstat->bssrateset + 8, &pattrib->pktlen);
3033 }
3034
3035 if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
3036
3037
3038 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie,
3039 pnetwork->IELength);
3040 if (p && p[1]) {
3041 memcpy(pframe, p, p[1] + 2);
3042 pframe += (p[1] + 2);
3043 pattrib->pktlen += (p[1] + 2);
3044 }
3045
3046
3047
3048 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie,
3049 pnetwork->IELength);
3050 if (p && p[1] > 0) {
3051 memcpy(pframe, p, p[1] + 2);
3052 pframe += (p[1] + 2);
3053 pattrib->pktlen += (p[1] + 2);
3054 }
3055 }
3056
3057
3058 if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) {
3059 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
3060 0x01, 0x01};
3061 int ie_len = 0;
3062
3063 for (p = ie; ; p += (ie_len + 2)) {
3064 p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
3065 pnetwork->IELength - (ie_len + 2));
3066 if (p)
3067 ie_len = p[1];
3068 else
3069 ie_len = 0;
3070 if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) {
3071 memcpy(pframe, p, ie_len + 2);
3072 pframe += (ie_len + 2);
3073 pattrib->pktlen += (ie_len + 2);
3074
3075 break;
3076 }
3077
3078 if (!p || ie_len == 0)
3079 break;
3080 }
3081 }
3082
3083 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
3084 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3085 REALTEK_96B_IE, &pattrib->pktlen);
3086 }
3087
3088 pattrib->last_txcmdsz = pattrib->pktlen;
3089
3090 dump_mgntframe23a(padapter, pmgntframe);
3091}
3092#endif
3093
3094static void issue_assocreq(struct rtw_adapter *padapter)
3095{
3096 int ret = _FAIL;
3097 struct xmit_frame *pmgntframe;
3098 struct pkt_attrib *pattrib;
3099 unsigned char *pframe;
3100 const u8 *p;
3101 struct ieee80211_mgmt *mgmt;
3102 unsigned int i, j, index = 0;
3103 unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
3104 struct registry_priv *pregpriv = &padapter->registrypriv;
3105 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3106 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3107 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3108 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3109 int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
3110 u8 *pie;
3111
3112 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3113 if (!pmgntframe)
3114 goto exit;
3115
3116
3117 pattrib = &pmgntframe->attrib;
3118 update_mgntframe_attrib23a(padapter, pattrib);
3119
3120 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3121
3122 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
3123 mgmt = (struct ieee80211_mgmt *)pframe;
3124
3125 mgmt->frame_control =
3126 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ);
3127
3128 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
3129 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3130 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3131
3132 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3133 pmlmeext->mgnt_seq++;
3134
3135
3136 put_unaligned_le16(pmlmeinfo->network.capability,
3137 &mgmt->u.assoc_req.capab_info);
3138
3139 put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval);
3140
3141 pframe = mgmt->u.assoc_req.variable;
3142 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
3143
3144
3145 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
3146 pmlmeinfo->network.Ssid.ssid_len,
3147 pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
3148
3149
3150
3151 get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
3152
3153
3154
3155 if (pmlmeext->cur_channel == 14)
3156 sta_bssrate_len = 4;
3157
3158
3159
3160
3161
3162 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3163 if (pmlmeinfo->network.SupportedRates[i] == 0)
3164 break;
3165 DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
3166 pmlmeinfo->network.SupportedRates[i]);
3167 }
3168
3169 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3170 if (pmlmeinfo->network.SupportedRates[i] == 0)
3171 break;
3172
3173
3174
3175 for (j = 0; j < sta_bssrate_len; j++) {
3176
3177
3178 if ((pmlmeinfo->network.SupportedRates[i] |
3179 IEEE80211_BASIC_RATE_MASK) ==
3180 (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
3181
3182 break;
3183 }
3184 }
3185
3186 if (j == sta_bssrate_len) {
3187
3188 DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
3189 "STA!\n", __func__, i,
3190 pmlmeinfo->network.SupportedRates[i]);
3191 } else {
3192
3193 bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
3194 }
3195 }
3196
3197 bssrate_len = index;
3198 DBG_8723A("bssrate_len = %d\n", bssrate_len);
3199
3200 if (bssrate_len == 0) {
3201 rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
3202 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
3203 goto exit;
3204 }
3205
3206 if (bssrate_len > 8) {
3207 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3208 bssrate, &pattrib->pktlen);
3209 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3210 (bssrate_len - 8), (bssrate + 8),
3211 &pattrib->pktlen);
3212 } else
3213 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3214 bssrate_len, bssrate, &pattrib->pktlen);
3215
3216
3217
3218 pie = pmlmeinfo->network.IEs;
3219 pie_len = pmlmeinfo->network.IELength;
3220
3221 p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
3222 if (p)
3223 pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
3224 &pattrib->pktlen);
3225
3226
3227 if (padapter->mlmepriv.htpriv.ht_option) {
3228 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
3229
3230 if (p && !is_ap_in_tkip23a(padapter)) {
3231 struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap;
3232
3233 memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap));
3234
3235
3236 if (pregpriv->cbw40_enable == 0) {
3237 cap->cap_info &= ~cpu_to_le16(
3238 IEEE80211_HT_CAP_SGI_40 |
3239 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3240 } else {
3241 cap->cap_info |= cpu_to_le16(
3242 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3243 }
3244
3245
3246 cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
3247
3248 rf_type = rtl8723a_get_rf_type(padapter);
3249
3250 switch (rf_type) {
3251 case RF_1T1R:
3252
3253 if (pregpriv->rx_stbc)
3254 cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3255
3256 memcpy(&cap->mcs, MCS_rate_1R23A, 16);
3257 break;
3258
3259 case RF_2T2R:
3260 case RF_1T2R:
3261 default:
3262
3263 if (pregpriv->rx_stbc == 0x3 ||
3264 (pmlmeext->cur_wireless_mode &
3265 WIRELESS_11_24N &&
3266
3267 pregpriv->rx_stbc == 0x1) ||
3268 (pmlmeext->cur_wireless_mode &
3269 WIRELESS_11_5N &&
3270 pregpriv->rx_stbc == 0x2) ||
3271
3272 pregpriv->wifi_spec == 1) {
3273 DBG_8723A("declare supporting RX "
3274 "STBC\n");
3275
3276 cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3277 }
3278 memcpy(&cap->mcs, MCS_rate_2R23A, 16);
3279 break;
3280 }
3281
3282 if (rtl8723a_BT_coexist(padapter) &&
3283 rtl8723a_BT_using_antenna_1(padapter)) {
3284
3285 cap->ampdu_params_info &=
3286 ~IEEE80211_HT_AMPDU_PARM_FACTOR;
3287
3288 }
3289
3290 pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
3291 p[1], (u8 *)&pmlmeinfo->ht_cap,
3292 &pattrib->pktlen);
3293 }
3294 }
3295
3296
3297 for (i = 0; i < pmlmeinfo->network.IELength;) {
3298 p = pmlmeinfo->network.IEs + i;
3299
3300 switch (p[0]) {
3301 case WLAN_EID_VENDOR_SPECIFIC:
3302 if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) ||
3303 !memcmp(p + 2, WMM_OUI23A, 4) ||
3304 !memcmp(p + 2, WPS_OUI23A, 4)) {
3305 u8 plen = p[1];
3306
3307 if (!padapter->registrypriv.wifi_spec) {
3308
3309
3310
3311
3312 if (!memcmp(p + 2, WPS_OUI23A, 4))
3313 plen = 14;
3314 }
3315 pframe = rtw_set_ie23a(pframe,
3316 WLAN_EID_VENDOR_SPECIFIC,
3317 plen, p + 2,
3318 &pattrib->pktlen);
3319 }
3320 break;
3321
3322 default:
3323 break;
3324 }
3325
3326 i += p[1] + 2;
3327 }
3328
3329 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3330 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3331 REALTEK_96B_IE, &pattrib->pktlen);
3332
3333 pattrib->last_txcmdsz = pattrib->pktlen;
3334 dump_mgntframe23a(padapter, pmgntframe);
3335
3336 ret = _SUCCESS;
3337
3338exit:
3339 pmlmepriv->assoc_req_len = 0;
3340 if (ret == _SUCCESS) {
3341 kfree(pmlmepriv->assoc_req);
3342 pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
3343 if (pmlmepriv->assoc_req) {
3344 memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen);
3345 pmlmepriv->assoc_req_len = pattrib->pktlen;
3346 }
3347 } else
3348 kfree(pmlmepriv->assoc_req);
3349
3350 return;
3351}
3352
3353
3354static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3355 unsigned int power_mode, int wait_ack)
3356{
3357 int ret = _FAIL;
3358 struct xmit_frame *pmgntframe;
3359 struct pkt_attrib *pattrib;
3360 unsigned char *pframe;
3361 struct ieee80211_hdr *pwlanhdr;
3362 struct xmit_priv *pxmitpriv;
3363 struct mlme_ext_priv *pmlmeext;
3364 struct mlme_ext_info *pmlmeinfo;
3365
3366
3367
3368 if (!padapter)
3369 goto exit;
3370
3371 pxmitpriv = &padapter->xmitpriv;
3372 pmlmeext = &padapter->mlmeextpriv;
3373 pmlmeinfo = &pmlmeext->mlmext_info;
3374
3375 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3376 if (!pmgntframe)
3377 goto exit;
3378
3379
3380 pattrib = &pmgntframe->attrib;
3381 update_mgntframe_attrib23a(padapter, pattrib);
3382 pattrib->retry_ctrl = false;
3383
3384 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3385
3386 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3387 pwlanhdr = (struct ieee80211_hdr *)pframe;
3388
3389 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3390 IEEE80211_STYPE_NULLFUNC);
3391
3392 if ((pmlmeinfo->state&0x03) == MSR_AP)
3393 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3394 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3395 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3396
3397 if (power_mode)
3398 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
3399
3400 ether_addr_copy(pwlanhdr->addr1, da);
3401 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3402 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3403
3404 pwlanhdr->seq_ctrl =
3405 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3406 pmlmeext->mgnt_seq++;
3407
3408 pframe += sizeof(struct ieee80211_hdr_3addr);
3409 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3410
3411 pattrib->last_txcmdsz = pattrib->pktlen;
3412
3413 if (wait_ack)
3414 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3415 else {
3416 dump_mgntframe23a(padapter, pmgntframe);
3417 ret = _SUCCESS;
3418 }
3419
3420exit:
3421 return ret;
3422}
3423
3424
3425
3426int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3427 unsigned int power_mode, int try_cnt, int wait_ms)
3428{
3429 int ret;
3430 int i = 0;
3431 unsigned long start = jiffies;
3432 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3433 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3434
3435
3436 if (da == NULL)
3437 da = get_my_bssid23a(&pmlmeinfo->network);
3438
3439 do {
3440 ret = _issue_nulldata23a(padapter, da, power_mode,
3441 wait_ms > 0 ? true : false);
3442
3443 i++;
3444
3445 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3446 break;
3447
3448 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3449 msleep(wait_ms);
3450
3451 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3452
3453 if (ret != _FAIL) {
3454 ret = _SUCCESS;
3455 goto exit;
3456 }
3457
3458 if (try_cnt && wait_ms) {
3459 if (da)
3460 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3461 __func__, padapter->pnetdev->name,
3462 da, rtw_get_oper_ch23a(padapter),
3463 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3464 jiffies_to_msecs(jiffies - start));
3465 else
3466 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3467 __func__, padapter->pnetdev->name,
3468 rtw_get_oper_ch23a(padapter),
3469 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3470 jiffies_to_msecs(jiffies - start));
3471 }
3472exit:
3473 return ret;
3474}
3475
3476
3477static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
3478 unsigned char *da, u16 tid, int wait_ack)
3479{
3480 int ret = _FAIL;
3481 struct xmit_frame *pmgntframe;
3482 struct pkt_attrib *pattrib;
3483 unsigned char *pframe;
3484 struct ieee80211_qos_hdr *pwlanhdr;
3485 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3486 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3487 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3488
3489 DBG_8723A("%s\n", __func__);
3490
3491 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3492 if (!pmgntframe)
3493 goto exit;
3494
3495
3496 pattrib = &pmgntframe->attrib;
3497 update_mgntframe_attrib23a(padapter, pattrib);
3498
3499 pattrib->hdrlen += 2;
3500 pattrib->qos_en = true;
3501 pattrib->eosp = 1;
3502 pattrib->ack_policy = 0;
3503 pattrib->mdata = 0;
3504
3505 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3506
3507 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3508 pwlanhdr = (struct ieee80211_qos_hdr *)pframe;
3509
3510 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3511 IEEE80211_STYPE_QOS_NULLFUNC);
3512
3513 if ((pmlmeinfo->state&0x03) == MSR_AP)
3514 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3515 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3516 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3517
3518 if (pattrib->mdata)
3519 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
3520
3521 pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK);
3522 pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) &
3523 IEEE80211_QOS_CTL_ACK_POLICY_MASK);
3524 if (pattrib->eosp)
3525 pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
3526
3527 ether_addr_copy(pwlanhdr->addr1, da);
3528 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3529 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3530
3531 pwlanhdr->seq_ctrl =
3532 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3533 pmlmeext->mgnt_seq++;
3534
3535 pframe += sizeof(struct ieee80211_qos_hdr);
3536 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3537
3538 pattrib->last_txcmdsz = pattrib->pktlen;
3539
3540 if (wait_ack)
3541 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3542 else {
3543 dump_mgntframe23a(padapter, pmgntframe);
3544 ret = _SUCCESS;
3545 }
3546
3547exit:
3548 return ret;
3549}
3550
3551
3552
3553int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3554 u16 tid, int try_cnt, int wait_ms)
3555{
3556 int ret;
3557 int i = 0;
3558 unsigned long start = jiffies;
3559 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3560 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3561
3562
3563 if (da == NULL)
3564 da = get_my_bssid23a(&pmlmeinfo->network);
3565
3566 do {
3567 ret = _issue_qos_nulldata23a(padapter, da, tid,
3568 wait_ms > 0 ? true : false);
3569
3570 i++;
3571
3572 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3573 break;
3574
3575 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3576 msleep(wait_ms);
3577 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3578
3579 if (ret != _FAIL) {
3580 ret = _SUCCESS;
3581 goto exit;
3582 }
3583
3584 if (try_cnt && wait_ms) {
3585 if (da)
3586 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3587 __func__, padapter->pnetdev->name,
3588 da, rtw_get_oper_ch23a(padapter),
3589 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3590 jiffies_to_msecs(jiffies - start));
3591 else
3592 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3593 __func__, padapter->pnetdev->name,
3594 rtw_get_oper_ch23a(padapter),
3595 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3596 jiffies_to_msecs(jiffies - start));
3597 }
3598exit:
3599 return ret;
3600}
3601
3602static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da,
3603 unsigned short reason, u8 wait_ack)
3604{
3605 struct xmit_frame *pmgntframe;
3606 struct pkt_attrib *pattrib;
3607 struct ieee80211_mgmt *mgmt;
3608 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3609 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3610 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3611 int ret = _FAIL;
3612
3613
3614
3615 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3616 if (!pmgntframe)
3617 goto exit;
3618
3619
3620 pattrib = &pmgntframe->attrib;
3621 update_mgntframe_attrib23a(padapter, pattrib);
3622 pattrib->retry_ctrl = false;
3623
3624 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3625
3626 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3627
3628 mgmt->frame_control =
3629 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
3630
3631 ether_addr_copy(mgmt->da, da);
3632 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3633 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3634
3635 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3636 pmlmeext->mgnt_seq++;
3637
3638 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2;
3639
3640 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
3641
3642 pattrib->last_txcmdsz = pattrib->pktlen;
3643
3644 if (wait_ack)
3645 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3646 else {
3647 dump_mgntframe23a(padapter, pmgntframe);
3648 ret = _SUCCESS;
3649 }
3650
3651exit:
3652 return ret;
3653}
3654
3655int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
3656 unsigned short reason)
3657{
3658 DBG_8723A("%s to %pM\n", __func__, da);
3659 return _issue_deauth(padapter, da, reason, false);
3660}
3661
3662static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
3663 unsigned short reason, int try_cnt, int wait_ms)
3664{
3665 int ret;
3666 int i = 0;
3667 unsigned long start = jiffies;
3668
3669 do {
3670 ret = _issue_deauth(padapter, da, reason,
3671 wait_ms >0 ? true : false);
3672
3673 i++;
3674
3675 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3676 break;
3677
3678 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3679 msleep(wait_ms);
3680
3681 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3682
3683 if (ret != _FAIL) {
3684 ret = _SUCCESS;
3685 goto exit;
3686 }
3687
3688 if (try_cnt && wait_ms) {
3689 if (da)
3690 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3691 __func__, padapter->pnetdev->name,
3692 da, rtw_get_oper_ch23a(padapter),
3693 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3694 jiffies_to_msecs(jiffies - start));
3695 else
3696 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3697 __func__, padapter->pnetdev->name,
3698 rtw_get_oper_ch23a(padapter),
3699 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3700 jiffies_to_msecs(jiffies - start));
3701 }
3702exit:
3703 return ret;
3704}
3705
3706void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
3707 u8 *ra, u8 new_ch, u8 ch_offset)
3708{
3709 struct xmit_frame *pmgntframe;
3710 struct pkt_attrib *pattrib;
3711 unsigned char *pframe;
3712 struct ieee80211_mgmt *mgmt;
3713 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3714 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3715
3716 DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n",
3717 __func__, padapter->pnetdev->name, ra, new_ch, ch_offset);
3718
3719 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3720 if (!pmgntframe)
3721 return;
3722
3723
3724 pattrib = &pmgntframe->attrib;
3725 update_mgntframe_attrib23a(padapter, pattrib);
3726
3727 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3728
3729 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3730
3731 mgmt->frame_control =
3732 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3733
3734 ether_addr_copy(mgmt->da, ra);
3735 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3736 ether_addr_copy(mgmt->bssid, ra);
3737
3738 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3739 pmlmeext->mgnt_seq++;
3740
3741 mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
3742 mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
3743
3744 pframe = mgmt->u.action.u.chan_switch.variable;
3745 pattrib->pktlen = offsetof(struct ieee80211_mgmt,
3746 u.action.u.chan_switch.variable);
3747
3748 pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
3749 new_ch, 0);
3750 pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
3751 hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
3752
3753 pattrib->last_txcmdsz = pattrib->pktlen;
3754
3755 dump_mgntframe23a(padapter, pmgntframe);
3756}
3757
3758void issue_action_BA23a(struct rtw_adapter *padapter,
3759 const unsigned char *raddr,
3760 unsigned char action, unsigned short status)
3761{
3762 u16 start_seq;
3763 u16 BA_para_set;
3764 u16 BA_starting_seqctrl;
3765 u16 BA_para;
3766 int max_rx_ampdu_factor;
3767 struct xmit_frame *pmgntframe;
3768 struct pkt_attrib *pattrib;
3769 struct ieee80211_mgmt *mgmt;
3770 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3771 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3772 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3773 struct sta_info *psta;
3774 struct sta_priv *pstapriv = &padapter->stapriv;
3775 struct registry_priv *pregpriv = &padapter->registrypriv;
3776 u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
3777
3778 DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status);
3779
3780 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3781 if (!pmgntframe)
3782 return;
3783
3784
3785 pattrib = &pmgntframe->attrib;
3786 update_mgntframe_attrib23a(padapter, pattrib);
3787
3788 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3789
3790 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3791
3792 mgmt->frame_control =
3793 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3794
3795 ether_addr_copy(mgmt->da, raddr);
3796 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3797 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3798
3799 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3800 pmlmeext->mgnt_seq++;
3801
3802 mgmt->u.action.category = WLAN_CATEGORY_BACK;
3803
3804 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1;
3805
3806 status = cpu_to_le16(status);
3807
3808 switch (action) {
3809 case WLAN_ACTION_ADDBA_REQ:
3810 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req);
3811
3812 mgmt->u.action.u.addba_req.action_code = action;
3813
3814 do {
3815 pmlmeinfo->dialogToken++;
3816 } while (pmlmeinfo->dialogToken == 0);
3817
3818 mgmt->u.action.u.addba_req.dialog_token =
3819 pmlmeinfo->dialogToken;
3820
3821 if (rtl8723a_BT_coexist(padapter) &&
3822 rtl8723a_BT_using_antenna_1(padapter) &&
3823 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3824 memcmp(raddr, tendaAPMac, 3))) {
3825
3826 BA_para_set = 0;
3827
3828 BA_para_set |= (1 << 1) &
3829 IEEE80211_ADDBA_PARAM_POLICY_MASK;
3830
3831 BA_para_set |= (status << 2) &
3832 IEEE80211_ADDBA_PARAM_TID_MASK;
3833
3834 BA_para_set |= (8 << 6) &
3835 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3836 } else {
3837
3838 BA_para_set = 0x1002 | ((status & 0xf) << 2);
3839 }
3840
3841 put_unaligned_le16(BA_para_set,
3842 &mgmt->u.action.u.addba_req.capab);
3843
3844
3845 put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout);
3846
3847 psta = rtw_get_stainfo23a(pstapriv, raddr);
3848 if (psta) {
3849 int idx;
3850
3851 idx = status & 0x07;
3852 start_seq =
3853 (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1;
3854
3855 DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
3856 start_seq, idx);
3857
3858 psta->BA_starting_seqctrl[idx] = start_seq;
3859
3860 BA_starting_seqctrl = start_seq << 4;
3861 } else
3862 BA_starting_seqctrl = 0;
3863
3864 put_unaligned_le16(BA_starting_seqctrl,
3865 &mgmt->u.action.u.addba_req.start_seq_num);
3866
3867 break;
3868
3869 case WLAN_ACTION_ADDBA_RESP:
3870 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp);
3871
3872 mgmt->u.action.u.addba_resp.action_code = action;
3873 mgmt->u.action.u.addba_resp.dialog_token =
3874 pmlmeinfo->ADDBA_req.dialog_token;
3875 put_unaligned_le16(status,
3876 &mgmt->u.action.u.addba_resp.status);
3877
3878 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
3879 &max_rx_ampdu_factor);
3880
3881 BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
3882 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
3883 BA_para_set = BA_para | 0x1000;
3884 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
3885 BA_para_set = BA_para | 0x0800;
3886 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
3887 BA_para_set = BA_para | 0x0400;
3888 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
3889 BA_para_set = BA_para | 0x0200;
3890 else
3891 BA_para_set = BA_para | 0x1000;
3892
3893 if (rtl8723a_BT_coexist(padapter) &&
3894 rtl8723a_BT_using_antenna_1(padapter) &&
3895 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3896 memcmp(raddr, tendaAPMac, 3))) {
3897
3898 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3899 BA_para_set |= (8 << 6) &
3900 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3901 }
3902
3903 if (pregpriv->ampdu_amsdu == 0)
3904 BA_para_set &= ~BIT(0);
3905 else if (pregpriv->ampdu_amsdu == 1)
3906 BA_para_set |= BIT(0);
3907
3908 put_unaligned_le16(BA_para_set,
3909 &mgmt->u.action.u.addba_resp.capab);
3910
3911 put_unaligned_le16(pmlmeinfo->ADDBA_req.BA_timeout_value,
3912 &mgmt->u.action.u.addba_resp.timeout);
3913
3914 pattrib->pktlen += 8;
3915 break;
3916 case WLAN_ACTION_DELBA:
3917 pattrib->pktlen += sizeof(mgmt->u.action.u.delba);
3918
3919 mgmt->u.action.u.delba.action_code = action;
3920 BA_para_set = (status & 0x1F) << 3;
3921 mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set);
3922 mgmt->u.action.u.delba.reason_code =
3923 cpu_to_le16(WLAN_REASON_QSTA_NOT_USE);
3924
3925 pattrib->pktlen += 5;
3926 break;
3927 default:
3928 break;
3929 }
3930
3931 pattrib->last_txcmdsz = pattrib->pktlen;
3932
3933 dump_mgntframe23a(padapter, pmgntframe);
3934}
3935
3936int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
3937{
3938 struct sta_priv *pstapriv = &padapter->stapriv;
3939 struct sta_info *psta = NULL;
3940
3941 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3942 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3943 u16 tid;
3944
3945 if ((pmlmeinfo->state&0x03) != MSR_AP)
3946 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3947 return _SUCCESS;
3948
3949 psta = rtw_get_stainfo23a(pstapriv, addr);
3950 if (psta == NULL)
3951 return _SUCCESS;
3952
3953 if (initiator == 0) {
3954 for (tid = 0; tid < MAXTID; tid++) {
3955 if (psta->recvreorder_ctrl[tid].enable == true) {
3956 DBG_8723A("rx agg disable tid(%d)\n", tid);
3957 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3958 psta->recvreorder_ctrl[tid].enable = false;
3959 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
3960 }
3961 }
3962 } else if (initiator == 1) {
3963 for (tid = 0; tid < MAXTID; tid++) {
3964 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
3965 DBG_8723A("tx agg disable tid(%d)\n", tid);
3966 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3967 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3968 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3969
3970 }
3971 }
3972 }
3973 return _SUCCESS;
3974}
3975
3976int send_beacon23a(struct rtw_adapter *padapter)
3977{
3978 bool bxmitok;
3979 int issue = 0;
3980 int poll = 0;
3981 unsigned long start = jiffies;
3982 unsigned int passing_time;
3983
3984 rtl8723a_bcn_valid(padapter);
3985 do {
3986 issue_beacon23a(padapter, 100);
3987 issue++;
3988 do {
3989 yield();
3990 bxmitok = rtl8723a_get_bcn_valid(padapter);
3991 poll++;
3992 } while ((poll % 10) != 0 && !bxmitok &&
3993 !padapter->bSurpriseRemoved &&
3994 !padapter->bDriverStopped);
3995
3996 } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
3997 !padapter->bDriverStopped);
3998
3999 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4000 return _FAIL;
4001
4002 passing_time = jiffies_to_msecs(jiffies - start);
4003
4004 if (!bxmitok) {
4005 DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
4006 return _FAIL;
4007 } else {
4008
4009 if (passing_time > 100 || issue > 3)
4010 DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
4011 __func__, issue, poll, passing_time);
4012 return _SUCCESS;
4013 }
4014}
4015
4016
4017
4018
4019
4020
4021
4022bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
4023{
4024
4025 int i = 0;
4026 u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
4027 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
4028 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
4029 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
4030 161, 163, 165};
4031 for (i = 0; i < sizeof(Channel_5G); i++)
4032 if (channel == Channel_5G[i])
4033 return true;
4034 return false;
4035}
4036
4037static void rtw_site_survey(struct rtw_adapter *padapter)
4038{
4039 unsigned char survey_channel = 0;
4040 enum rt_scan_type ScanType = SCAN_PASSIVE;
4041 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4042 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4043 struct rtw_ieee80211_channel *ch;
4044
4045 if (pmlmeext->sitesurvey_res.channel_idx <
4046 pmlmeext->sitesurvey_res.ch_num) {
4047 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
4048 survey_channel = ch->hw_value;
4049 ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ?
4050 SCAN_PASSIVE : SCAN_ACTIVE;
4051 }
4052
4053 if (survey_channel != 0) {
4054
4055 if (pmlmeext->sitesurvey_res.channel_idx == 0)
4056 set_channel_bwmode23a(padapter, survey_channel,
4057 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
4058 HT_CHANNEL_WIDTH_20);
4059 else
4060 SelectChannel23a(padapter, survey_channel);
4061
4062 if (ScanType == SCAN_ACTIVE)
4063 {
4064 int i;
4065
4066 for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
4067 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
4068
4069 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4070
4071 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4072 }
4073 }
4074
4075 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4076
4077 issue_probereq(padapter, NULL, NULL);
4078
4079 issue_probereq(padapter, NULL, NULL);
4080 }
4081 }
4082
4083 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
4084 } else {
4085
4086 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
4087
4088
4089
4090 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
4091 pmlmeext->cur_ch_offset,
4092 pmlmeext->cur_bwmode);
4093
4094
4095
4096
4097
4098 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4099
4100
4101 rtl8723a_set_initial_gain(padapter, 0xff);
4102
4103 rtl8723a_odm_support_ability_restore(padapter);
4104
4105 if (is_client_associated_to_ap23a(padapter) == true)
4106 issue_nulldata23a(padapter, NULL, 0, 3, 500);
4107
4108 rtl8723a_mlme_sitesurvey(padapter, 0);
4109
4110 report_surveydone_event23a(padapter);
4111
4112 pmlmeext->chan_scan_time = SURVEY_TO;
4113 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
4114 }
4115
4116 return;
4117}
4118
4119
4120static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
4121 struct recv_frame *precv_frame)
4122{
4123 struct sk_buff *skb = precv_frame->pkt;
4124 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
4125 struct registry_priv *pregistrypriv = &padapter->registrypriv;
4126 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4127 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4128 struct wlan_bssid_ex *bssid;
4129 const u8 *p;
4130 u8 *pie;
4131 unsigned int length;
4132 int i;
4133
4134 length = skb->len;
4135
4136 bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
4137 if (!bssid)
4138 return NULL;
4139
4140 if (ieee80211_is_beacon(mgmt->frame_control)) {
4141 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4142 pie = mgmt->u.beacon.variable;
4143 bssid->reserved = 1;
4144 bssid->capability =
4145 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4146 bssid->beacon_interval =
4147 get_unaligned_le16(&mgmt->u.beacon.beacon_int);
4148 bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
4149 } else if (ieee80211_is_probe_req(mgmt->frame_control)) {
4150 length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
4151 pie = mgmt->u.probe_req.variable;
4152 bssid->reserved = 2;
4153 bssid->capability = 0;
4154 bssid->beacon_interval =
4155 padapter->registrypriv.dev_network.beacon_interval;
4156 bssid->tsf = 0;
4157 } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
4158 length -=
4159 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
4160 pie = mgmt->u.probe_resp.variable;
4161 bssid->reserved = 3;
4162 bssid->capability =
4163 get_unaligned_le16(&mgmt->u.probe_resp.capab_info);
4164 bssid->beacon_interval =
4165 get_unaligned_le16(&mgmt->u.probe_resp.beacon_int);
4166 bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp);
4167 } else {
4168 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4169 pie = mgmt->u.beacon.variable;
4170 bssid->reserved = 0;
4171 bssid->capability =
4172 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4173 bssid->beacon_interval =
4174 padapter->registrypriv.dev_network.beacon_interval;
4175 bssid->tsf = 0;
4176 }
4177
4178 if (length > MAX_IE_SZ) {
4179
4180 kfree(bssid);
4181 return NULL;
4182 }
4183
4184 bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
4185
4186
4187 bssid->IELength = length;
4188 memcpy(bssid->IEs, pie, bssid->IELength);
4189
4190
4191
4192 bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
4193 bssid->SignalQuality =
4194 precv_frame->attrib.phy_info.SignalQuality;
4195 bssid->SignalStrength =
4196 precv_frame->attrib.phy_info.SignalStrength;
4197
4198
4199 p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength);
4200
4201 if (!p) {
4202 DBG_8723A("marc: cannot find SSID for survey event\n");
4203 goto fail;
4204 }
4205
4206 if (p[1] > IEEE80211_MAX_SSID_LEN) {
4207 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4208 "event\n", __func__, __LINE__, p[1]);
4209 goto fail;
4210 }
4211 memcpy(bssid->Ssid.ssid, p + 2, p[1]);
4212 bssid->Ssid.ssid_len = p[1];
4213
4214
4215 i = 0;
4216 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength);
4217 if (p) {
4218 if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
4219 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4220 "event\n", __func__, __LINE__, p[1]);
4221 goto fail;
4222 }
4223 memcpy(bssid->SupportedRates, p + 2, p[1]);
4224 i = p[1];
4225 }
4226
4227 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs,
4228 bssid->IELength);
4229 if (p) {
4230 if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
4231 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4232 "event\n", __func__, __LINE__, p[1]);
4233 goto fail;
4234 }
4235 memcpy(bssid->SupportedRates + i, p + 2, p[1]);
4236 }
4237
4238
4239 p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength);
4240
4241 bssid->DSConfig = 0;
4242
4243 if (p) {
4244 bssid->DSConfig = p[2];
4245 } else {
4246
4247 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs,
4248 bssid->IELength);
4249 if (p) {
4250 struct ieee80211_ht_operation *HT_info =
4251 (struct ieee80211_ht_operation *)(p + 2);
4252 bssid->DSConfig = HT_info->primary_chan;
4253 } else
4254 bssid->DSConfig = rtw_get_oper_ch23a(padapter);
4255 }
4256
4257 if (ieee80211_is_probe_req(mgmt->frame_control)) {
4258
4259 bssid->ifmode = NL80211_IFTYPE_STATION;
4260 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4261 bssid->Privacy = 1;
4262 return bssid;
4263 }
4264
4265 if (bssid->capability & WLAN_CAPABILITY_ESS) {
4266 bssid->ifmode = NL80211_IFTYPE_STATION;
4267 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4268 } else {
4269 bssid->ifmode = NL80211_IFTYPE_ADHOC;
4270 ether_addr_copy(bssid->MacAddress, mgmt->bssid);
4271 }
4272
4273 if (bssid->capability & WLAN_CAPABILITY_PRIVACY)
4274 bssid->Privacy = 1;
4275 else
4276 bssid->Privacy = 0;
4277
4278 bssid->ATIMWindow = 0;
4279
4280
4281 if (pregistrypriv->wifi_spec == 1 &&
4282 pmlmeinfo->bwmode_updated == false) {
4283 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4284
4285 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs,
4286 bssid->IELength);
4287 if (p && p[1] > 0) {
4288 struct ieee80211_ht_cap *pHT_caps;
4289
4290 pHT_caps = (struct ieee80211_ht_cap *)(p + 2);
4291
4292 if (pHT_caps->cap_info &
4293 cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT))
4294 pmlmepriv->num_FortyMHzIntolerant++;
4295 } else
4296 pmlmepriv->num_sta_no_ht++;
4297 }
4298
4299
4300
4301 if (bssid->DSConfig != rtw_get_oper_ch23a(padapter))
4302 bssid->SignalQuality = 101;
4303
4304 return bssid;
4305fail:
4306 kfree (bssid);
4307 return NULL;
4308}
4309
4310static void start_create_ibss(struct rtw_adapter *padapter)
4311{
4312 unsigned short caps;
4313 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4314 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4315 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4316
4317 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4318 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4319
4320
4321 update_wireless_mode23a(padapter);
4322
4323
4324 caps = pnetwork->capability;
4325 update_capinfo23a(padapter, caps);
4326 if (caps & WLAN_CAPABILITY_IBSS) {
4327 rtl8723a_set_sec_cfg(padapter, 0xcf);
4328
4329
4330
4331 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
4332
4333 rtl8723a_SetBeaconRelatedRegisters(padapter);
4334
4335
4336 pmlmeinfo->state = MSR_ADHOC;
4337 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4338
4339
4340 if (send_beacon23a(padapter) == _FAIL) {
4341 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
4342 "issuing beacon frame fail....\n");
4343
4344 report_join_res23a(padapter, -1);
4345 pmlmeinfo->state = MSR_NOLINK;
4346 } else {
4347 hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
4348 hw_var_set_mlme_join(padapter, 0);
4349
4350 report_join_res23a(padapter, 1);
4351 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4352 }
4353 } else {
4354 DBG_8723A("%s: invalid cap:%x\n", __func__, caps);
4355 return;
4356 }
4357}
4358
4359static void start_clnt_join(struct rtw_adapter *padapter)
4360{
4361 unsigned short caps;
4362 u8 val8;
4363 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4364 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4365 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4366 int beacon_timeout;
4367
4368 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4369 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4370
4371
4372 update_wireless_mode23a(padapter);
4373
4374
4375 caps = pnetwork->capability;
4376 update_capinfo23a(padapter, caps);
4377 if (caps & WLAN_CAPABILITY_ESS) {
4378
4379 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4380
4381 rtl8723a_set_media_status(padapter, MSR_INFRA);
4382
4383 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
4384 0xcc: 0xcf;
4385
4386 rtl8723a_set_sec_cfg(padapter, val8);
4387
4388
4389
4390
4391
4392
4393 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
4394 set_link_timer(pmlmeext, beacon_timeout);
4395 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
4396 msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
4397 pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA;
4398 } else if (caps & WLAN_CAPABILITY_IBSS) {
4399 rtl8723a_set_media_status(padapter, MSR_ADHOC);
4400
4401 rtl8723a_set_sec_cfg(padapter, 0xcf);
4402
4403
4404 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4405
4406 rtl8723a_SetBeaconRelatedRegisters(padapter);
4407
4408 pmlmeinfo->state = MSR_ADHOC;
4409
4410 report_join_res23a(padapter, 1);
4411 } else {
4412
4413 return;
4414 }
4415}
4416
4417static void start_clnt_auth(struct rtw_adapter *padapter)
4418{
4419 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4420 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4421
4422 del_timer_sync(&pmlmeext->link_timer);
4423
4424 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4425 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4426
4427 pmlmeinfo->auth_seq = 1;
4428 pmlmeinfo->reauth_count = 0;
4429 pmlmeinfo->reassoc_count = 0;
4430 pmlmeinfo->link_count = 0;
4431 pmlmeext->retry = 0;
4432
4433
4434
4435
4436
4437
4438
4439 issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress,
4440 WLAN_REASON_DEAUTH_LEAVING);
4441
4442 DBG_8723A_LEVEL(_drv_always_, "start auth\n");
4443 issue_auth(padapter, NULL, 0);
4444
4445 set_link_timer(pmlmeext, REAUTH_TO);
4446}
4447
4448static void start_clnt_assoc(struct rtw_adapter *padapter)
4449{
4450 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4451 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4452
4453 del_timer_sync(&pmlmeext->link_timer);
4454
4455 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4456 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4457
4458 issue_assocreq(padapter);
4459
4460 set_link_timer(pmlmeext, REASSOC_TO);
4461}
4462
4463int receive_disconnect23a(struct rtw_adapter *padapter,
4464 unsigned char *MacAddr, unsigned short reason)
4465{
4466 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4467 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4468
4469
4470 if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
4471 return _SUCCESS;
4472
4473 DBG_8723A("%s\n", __func__);
4474
4475 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
4476 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4477 pmlmeinfo->state = MSR_NOLINK;
4478 report_del_sta_event23a(padapter, MacAddr, reason);
4479
4480 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4481 pmlmeinfo->state = MSR_NOLINK;
4482 report_join_res23a(padapter, -2);
4483 }
4484 }
4485
4486 return _SUCCESS;
4487}
4488
4489static void process_80211d(struct rtw_adapter *padapter,
4490 struct wlan_bssid_ex *bssid)
4491{
4492 struct registry_priv *pregistrypriv;
4493 struct mlme_ext_priv *pmlmeext;
4494 struct rt_channel_info *chplan_new;
4495 u8 channel;
4496 u8 i;
4497
4498 pregistrypriv = &padapter->registrypriv;
4499 pmlmeext = &padapter->mlmeextpriv;
4500
4501
4502 if (pregistrypriv->enable80211d &&
4503 !pmlmeext->update_channel_plan_by_ap_done) {
4504 const u8 *ie, *p;
4505 struct rt_channel_plan chplan_ap;
4506 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4507 u8 country[4];
4508 u8 fcn;
4509 u8 noc;
4510 u8 j, k;
4511
4512 ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs,
4513 bssid->IELength);
4514 if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
4515 return;
4516
4517 p = ie + 2;
4518 ie += ie[1];
4519 ie += 2;
4520
4521 memcpy(country, p, 3);
4522 country[3] = '\0';
4523
4524 p += 3;
4525 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4526 "%s: 802.11d country =%s\n", __func__, country);
4527
4528 i = 0;
4529 while ((ie - p) >= 3) {
4530 fcn = *(p++);
4531 noc = *(p++);
4532 p++;
4533
4534 for (j = 0; j < noc; j++) {
4535 if (fcn <= 14)
4536 channel = fcn + j;
4537 else
4538 channel = fcn + j * 4;
4539
4540 chplan_ap.Channel[i++] = channel;
4541 }
4542 }
4543 chplan_ap.Len = i;
4544
4545 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4546 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4547 chplan_new = pmlmeext->channel_set;
4548
4549 i = j = k = 0;
4550 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4551 do {
4552 if (i == MAX_CHANNEL_NUM ||
4553 chplan_sta[i].ChannelNum == 0 ||
4554 chplan_sta[i].ChannelNum > 14)
4555 break;
4556
4557 if (j == chplan_ap.Len ||
4558 chplan_ap.Channel[j] > 14)
4559 break;
4560
4561 if (chplan_sta[i].ChannelNum ==
4562 chplan_ap.Channel[j]) {
4563 chplan_new[k].ChannelNum =
4564 chplan_ap.Channel[j];
4565 chplan_new[k].ScanType = SCAN_ACTIVE;
4566 i++;
4567 j++;
4568 k++;
4569 } else if (chplan_sta[i].ChannelNum <
4570 chplan_ap.Channel[j]) {
4571 chplan_new[k].ChannelNum =
4572 chplan_sta[i].ChannelNum;
4573 chplan_new[k].ScanType =
4574 SCAN_PASSIVE;
4575 i++;
4576 k++;
4577 } else if (chplan_sta[i].ChannelNum >
4578 chplan_ap.Channel[j]) {
4579 chplan_new[k].ChannelNum =
4580 chplan_ap.Channel[j];
4581 chplan_new[k].ScanType =
4582 SCAN_ACTIVE;
4583 j++;
4584 k++;
4585 }
4586 } while (1);
4587
4588
4589 while (i < MAX_CHANNEL_NUM &&
4590 chplan_sta[i].ChannelNum != 0 &&
4591 chplan_sta[i].ChannelNum <= 14) {
4592 chplan_new[k].ChannelNum =
4593 chplan_sta[i].ChannelNum;
4594 chplan_new[k].ScanType = SCAN_PASSIVE;
4595 i++;
4596 k++;
4597 }
4598
4599
4600 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
4601 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4602 chplan_new[k].ScanType = SCAN_ACTIVE;
4603 j++;
4604 k++;
4605 }
4606 } else {
4607
4608 while (i < MAX_CHANNEL_NUM &&
4609 chplan_sta[i].ChannelNum != 0 &&
4610 chplan_sta[i].ChannelNum <= 14) {
4611 chplan_new[k].ChannelNum =
4612 chplan_sta[i].ChannelNum;
4613 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4614 i++;
4615 k++;
4616 }
4617
4618
4619 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
4620 j++;
4621 }
4622
4623 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4624 do {
4625 if (i == MAX_CHANNEL_NUM ||
4626 chplan_sta[i].ChannelNum == 0)
4627 break;
4628
4629 if (j == chplan_ap.Len ||
4630 chplan_ap.Channel[j] == 0)
4631 break;
4632
4633 if (chplan_sta[i].ChannelNum ==
4634 chplan_ap.Channel[j]) {
4635 chplan_new[k].ChannelNum =
4636 chplan_ap.Channel[j];
4637 chplan_new[k].ScanType = SCAN_ACTIVE;
4638 i++;
4639 j++;
4640 k++;
4641 } else if (chplan_sta[i].ChannelNum <
4642 chplan_ap.Channel[j]) {
4643 chplan_new[k].ChannelNum =
4644 chplan_sta[i].ChannelNum;
4645 chplan_new[k].ScanType = SCAN_PASSIVE;
4646 i++;
4647 k++;
4648 } else if (chplan_sta[i].ChannelNum >
4649 chplan_ap.Channel[j]) {
4650 chplan_new[k].ChannelNum =
4651 chplan_ap.Channel[j];
4652 chplan_new[k].ScanType = SCAN_ACTIVE;
4653 j++;
4654 k++;
4655 }
4656 } while (1);
4657
4658
4659 while (i < MAX_CHANNEL_NUM &&
4660 chplan_sta[i].ChannelNum != 0) {
4661 chplan_new[k].ChannelNum =
4662 chplan_sta[i].ChannelNum;
4663 chplan_new[k].ScanType = SCAN_PASSIVE;
4664 i++;
4665 k++;
4666 }
4667
4668
4669 while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
4670 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4671 chplan_new[k].ScanType = SCAN_ACTIVE;
4672 j++;
4673 k++;
4674 }
4675 } else {
4676
4677 while (i < MAX_CHANNEL_NUM &&
4678 chplan_sta[i].ChannelNum != 0) {
4679 chplan_new[k].ChannelNum =
4680 chplan_sta[i].ChannelNum;
4681 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4682 i++;
4683 k++;
4684 }
4685 }
4686 pmlmeext->update_channel_plan_by_ap_done = 1;
4687 }
4688
4689
4690 channel = bssid->DSConfig;
4691 chplan_new = pmlmeext->channel_set;
4692 i = 0;
4693 while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
4694 if (chplan_new[i].ChannelNum == channel) {
4695 if (chplan_new[i].ScanType == SCAN_PASSIVE) {
4696
4697
4698 if (channel >= 52 && channel <= 144)
4699 break;
4700
4701 chplan_new[i].ScanType = SCAN_ACTIVE;
4702 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4703 "%s: change channel %d scan type from passive to active\n",
4704 __func__, channel);
4705 }
4706 break;
4707 }
4708 i++;
4709 }
4710}
4711
4712
4713
4714
4715
4716
4717
4718void report_survey_event23a(struct rtw_adapter *padapter,
4719 struct recv_frame *precv_frame)
4720{
4721 struct cmd_obj *pcmd_obj;
4722 u8 *pevtcmd;
4723 u32 cmdsz;
4724 struct survey_event *psurvey_evt;
4725 struct C2HEvent_Header *pc2h_evt_hdr;
4726 struct mlme_ext_priv *pmlmeext;
4727 struct cmd_priv *pcmdpriv;
4728
4729 if (!padapter)
4730 return;
4731
4732 pmlmeext = &padapter->mlmeextpriv;
4733 pcmdpriv = &padapter->cmdpriv;
4734
4735 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4736 if (!pcmd_obj)
4737 return;
4738
4739 cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
4740 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4741 if (!pevtcmd) {
4742 kfree(pcmd_obj);
4743 return;
4744 }
4745
4746 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4747 pcmd_obj->cmdsz = cmdsz;
4748 pcmd_obj->parmbuf = pevtcmd;
4749
4750 pcmd_obj->rsp = NULL;
4751 pcmd_obj->rspsz = 0;
4752
4753 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4754 pc2h_evt_hdr->len = sizeof(struct survey_event);
4755 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4756 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4757
4758 psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4759
4760 psurvey_evt->bss = collect_bss_info(padapter, precv_frame);
4761 if (!psurvey_evt->bss) {
4762 kfree(pcmd_obj);
4763 kfree(pevtcmd);
4764 return;
4765 }
4766
4767 process_80211d(padapter, psurvey_evt->bss);
4768
4769 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4770
4771 pmlmeext->sitesurvey_res.bss_cnt++;
4772
4773 return;
4774}
4775
4776void report_surveydone_event23a(struct rtw_adapter *padapter)
4777{
4778 struct cmd_obj *pcmd_obj;
4779 u8 *pevtcmd;
4780 u32 cmdsz;
4781 struct surveydone_event *psurveydone_evt;
4782 struct C2HEvent_Header *pc2h_evt_hdr;
4783 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4784 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4785
4786 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4787 if (!pcmd_obj)
4788 return;
4789
4790 cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
4791 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4792 if (!pevtcmd) {
4793 kfree(pcmd_obj);
4794 return;
4795 }
4796
4797 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4798 pcmd_obj->cmdsz = cmdsz;
4799 pcmd_obj->parmbuf = pevtcmd;
4800
4801 pcmd_obj->rsp = NULL;
4802 pcmd_obj->rspsz = 0;
4803
4804 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4805 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4806 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4807 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4808
4809 psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4810 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4811
4812 DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
4813
4814 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4815
4816 return;
4817}
4818
4819void report_join_res23a(struct rtw_adapter *padapter, int res)
4820{
4821 struct cmd_obj *pcmd_obj;
4822 u8 *pevtcmd;
4823 u32 cmdsz;
4824 struct joinbss_event *pjoinbss_evt;
4825 struct C2HEvent_Header *pc2h_evt_hdr;
4826 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4827 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4828 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4829
4830 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4831 if (!pcmd_obj)
4832 return;
4833
4834 cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
4835 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4836 if (!pevtcmd) {
4837 kfree(pcmd_obj);
4838 return;
4839 }
4840
4841 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4842 pcmd_obj->cmdsz = cmdsz;
4843 pcmd_obj->parmbuf = pevtcmd;
4844
4845 pcmd_obj->rsp = NULL;
4846 pcmd_obj->rspsz = 0;
4847
4848 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4849 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4850 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4851 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4852
4853 pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4854 memcpy((unsigned char *)&pjoinbss_evt->network.network,
4855 &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
4856 pjoinbss_evt->network.join_res = res;
4857
4858 DBG_8723A("report_join_res23a(%d)\n", res);
4859
4860 rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
4861
4862 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4863
4864 return;
4865}
4866
4867void report_del_sta_event23a(struct rtw_adapter *padapter,
4868 unsigned char *MacAddr, unsigned short reason)
4869{
4870 struct cmd_obj *pcmd_obj;
4871 u8 *pevtcmd;
4872 u32 cmdsz;
4873 struct sta_info *psta;
4874 int mac_id;
4875 struct stadel_event *pdel_sta_evt;
4876 struct C2HEvent_Header *pc2h_evt_hdr;
4877 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4878 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4879
4880 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4881 if (!pcmd_obj)
4882 return;
4883
4884 cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
4885 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4886 if (!pevtcmd) {
4887 kfree(pcmd_obj);
4888 return;
4889 }
4890
4891 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4892 pcmd_obj->cmdsz = cmdsz;
4893 pcmd_obj->parmbuf = pevtcmd;
4894
4895 pcmd_obj->rsp = NULL;
4896 pcmd_obj->rspsz = 0;
4897
4898 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4899 pc2h_evt_hdr->len = sizeof(struct stadel_event);
4900 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4901 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4902
4903 pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4904 ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
4905 memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
4906 2);
4907
4908 psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
4909 if (psta)
4910 mac_id = (int)psta->mac_id;
4911 else
4912 mac_id = -1;
4913
4914 pdel_sta_evt->mac_id = mac_id;
4915
4916 DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
4917
4918 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4919
4920 return;
4921}
4922
4923void report_add_sta_event23a(struct rtw_adapter *padapter,
4924 unsigned char *MacAddr, int cam_idx)
4925{
4926 struct cmd_obj *pcmd_obj;
4927 u8 *pevtcmd;
4928 u32 cmdsz;
4929 struct stassoc_event *padd_sta_evt;
4930 struct C2HEvent_Header *pc2h_evt_hdr;
4931 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4932 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4933
4934 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4935 if (!pcmd_obj)
4936 return;
4937
4938 cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
4939 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4940 if (!pevtcmd) {
4941 kfree(pcmd_obj);
4942 return;
4943 }
4944
4945 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4946 pcmd_obj->cmdsz = cmdsz;
4947 pcmd_obj->parmbuf = pevtcmd;
4948
4949 pcmd_obj->rsp = NULL;
4950 pcmd_obj->rspsz = 0;
4951
4952 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4953 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4954 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4955 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4956
4957 padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4958 ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
4959 padd_sta_evt->cam_id = cam_idx;
4960
4961 DBG_8723A("report_add_sta_event23a: add STA\n");
4962
4963 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4964
4965 return;
4966}
4967
4968
4969
4970
4971
4972
4973
4974
4975void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
4976{
4977 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4978 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4979 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4980
4981
4982 VCS_update23a(padapter, psta);
4983
4984
4985 if (pmlmepriv->htpriv.ht_option) {
4986 psta->htpriv.ht_option = true;
4987
4988 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4989
4990 if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
4991 psta->htpriv.sgi = true;
4992
4993 psta->qos_option = true;
4994
4995 } else {
4996 psta->htpriv.ht_option = false;
4997
4998 psta->htpriv.ampdu_enable = false;
4999
5000 psta->htpriv.sgi = false;
5001 psta->qos_option = false;
5002
5003 }
5004 psta->htpriv.bwmode = pmlmeext->cur_bwmode;
5005 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
5006
5007 psta->htpriv.agg_enable_bitmap = 0x0;
5008 psta->htpriv.candidate_tid_bitmap = 0x0;
5009
5010
5011 if (pmlmepriv->qos_option)
5012 psta->qos_option = true;
5013
5014 psta->state = _FW_LINKED;
5015}
5016
5017void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter,
5018 int join_res)
5019{
5020 struct sta_info *psta, *psta_bmc;
5021 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5022 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5023 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5024 struct sta_priv *pstapriv = &padapter->stapriv;
5025
5026 if (join_res < 0) {
5027 hw_var_set_mlme_join(padapter, 1);
5028 hw_var_set_bssid(padapter, null_addr);
5029
5030
5031 update_tx_basic_rate23a(padapter,
5032 padapter->registrypriv.wireless_mode);
5033
5034 goto exit_mlmeext_joinbss_event_callback23a;
5035 }
5036
5037 if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
5038
5039 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
5040 if (psta_bmc) {
5041 pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
5042 update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
5043 Update_RA_Entry23a(padapter, psta_bmc);
5044 }
5045 }
5046
5047
5048 rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
5049
5050
5051 update_IOT_info23a(padapter);
5052
5053 HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
5054
5055
5056 rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
5057
5058
5059 update_capinfo23a(padapter, pmlmeinfo->capability);
5060
5061
5062 WMMOnAssocRsp23a(padapter);
5063
5064
5065 HTOnAssocRsp23a(padapter);
5066
5067
5068 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5069
5070 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
5071 if (psta) {
5072 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5073
5074
5075
5076 psta->wireless_mode = pmlmeext->cur_wireless_mode;
5077
5078
5079 set_sta_rate23a(padapter, psta);
5080 }
5081
5082 hw_var_set_mlme_join(padapter, 2);
5083
5084 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
5085
5086 rtw_correct_TSF(padapter);
5087
5088
5089 }
5090
5091 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
5092
5093exit_mlmeext_joinbss_event_callback23a:
5094 DBG_8723A("=>%s\n", __func__);
5095}
5096
5097void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter,
5098 struct sta_info *psta)
5099{
5100 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5101 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5102
5103 DBG_8723A("%s\n", __func__);
5104
5105 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
5106
5107 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5108
5109 } else {
5110
5111 rtw_correct_TSF(padapter);
5112
5113
5114 if (send_beacon23a(padapter) != _SUCCESS) {
5115 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5116
5117 pmlmeinfo->state ^= MSR_ADHOC;
5118
5119 return;
5120 }
5121
5122 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
5123 }
5124 hw_var_set_mlme_join(padapter, 2);
5125 }
5126
5127 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5128
5129
5130 Update_RA_Entry23a(padapter, psta);
5131
5132
5133 update_sta_info23a(padapter, psta);
5134}
5135
5136void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
5137{
5138 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5139 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5140
5141 if (is_client_associated_to_ap23a(padapter) ||
5142 is_IBSS_empty23a(padapter)) {
5143
5144
5145 hw_var_set_mlme_disconnect(padapter);
5146 hw_var_set_bssid(padapter, null_addr);
5147
5148
5149 update_tx_basic_rate23a(padapter,
5150 padapter->registrypriv.wireless_mode);
5151
5152
5153 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5154 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5155
5156 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5157 pmlmeext->cur_ch_offset,
5158 pmlmeext->cur_bwmode);
5159
5160 flush_all_cam_entry23a(padapter);
5161
5162 pmlmeinfo->state = MSR_NOLINK;
5163
5164
5165 rtl8723a_set_media_status(padapter, MSR_INFRA);
5166
5167 del_timer_sync(&pmlmeext->link_timer);
5168 }
5169}
5170
5171static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
5172{
5173 u8 ret = false;
5174
5175 if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) &&
5176 sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
5177 sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
5178 ret = false;
5179 else
5180 ret = true;
5181
5182 sta_update_last_rx_pkts(psta);
5183 return ret;
5184}
5185
5186void linked_status_chk23a(struct rtw_adapter *padapter)
5187{
5188 u32 i;
5189 struct sta_info *psta;
5190 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5191 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5192 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5193 struct sta_priv *pstapriv = &padapter->stapriv;
5194
5195 if (is_client_associated_to_ap23a(padapter)) {
5196
5197
5198 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5199 int rx_chk_limit;
5200
5201 rx_chk_limit = 4;
5202
5203 psta = rtw_get_stainfo23a(pstapriv,
5204 pmlmeinfo->network.MacAddress);
5205 if (psta) {
5206 bool is_p2p_enable = false;
5207
5208 if (chk_ap_is_alive(padapter, psta) == false)
5209 rx_chk = _FAIL;
5210
5211 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5212 tx_chk = _FAIL;
5213
5214 if (pmlmeext->active_keep_alive_check &&
5215 (rx_chk == _FAIL || tx_chk == _FAIL)) {
5216 u8 backup_oper_channel = 0;
5217
5218
5219
5220 if (rtw_get_oper_ch23a(padapter) !=
5221 pmlmeext->cur_channel) {
5222 backup_oper_channel =
5223 rtw_get_oper_ch23a(padapter);
5224 SelectChannel23a(padapter,
5225 pmlmeext->cur_channel);
5226 }
5227
5228 if (rx_chk != _SUCCESS)
5229 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
5230
5231 if ((tx_chk != _SUCCESS &&
5232 pmlmeinfo->link_count++ == 0xf) ||
5233 rx_chk != _SUCCESS) {
5234 tx_chk = issue_nulldata23a(padapter,
5235 psta->hwaddr,
5236 0, 3, 1);
5237
5238
5239
5240 if (tx_chk == _SUCCESS &&
5241 !is_p2p_enable)
5242 rx_chk = _SUCCESS;
5243 }
5244
5245
5246 if (backup_oper_channel>0)
5247 SelectChannel23a(padapter,
5248 backup_oper_channel);
5249 } else {
5250 if (rx_chk != _SUCCESS) {
5251 if (pmlmeext->retry == 0) {
5252 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5253 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5254 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5255 }
5256 }
5257
5258 if (tx_chk != _SUCCESS &&
5259 pmlmeinfo->link_count++ == 0xf)
5260 tx_chk = issue_nulldata23a(padapter,
5261 NULL, 0, 1,
5262 0);
5263 }
5264
5265 if (rx_chk == _FAIL) {
5266 pmlmeext->retry++;
5267 if (pmlmeext->retry > rx_chk_limit) {
5268 DBG_8723A_LEVEL(_drv_always_,
5269 "%s(%s): disconnect or "
5270 "roaming\n", __func__,
5271 padapter->pnetdev->name);
5272 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
5273 WLAN_REASON_EXPIRATION_CHK);
5274 return;
5275 }
5276 } else
5277 pmlmeext->retry = 0;
5278
5279 if (tx_chk == _FAIL)
5280 pmlmeinfo->link_count &= 0xf;
5281 else {
5282 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5283 pmlmeinfo->link_count = 0;
5284 }
5285
5286 }
5287 } else if (is_client_associated_to_ibss23a(padapter)) {
5288
5289
5290 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5291 if (pmlmeinfo->FW_sta_info[i].status == 1) {
5292 psta = pmlmeinfo->FW_sta_info[i].psta;
5293
5294 if (!psta)
5295 continue;
5296
5297 if (pmlmeinfo->FW_sta_info[i].rx_pkt ==
5298 sta_rx_pkts(psta)) {
5299
5300 if (pmlmeinfo->FW_sta_info[i].retry<3) {
5301 pmlmeinfo->FW_sta_info[i].retry++;
5302 } else {
5303 pmlmeinfo->FW_sta_info[i].retry = 0;
5304 pmlmeinfo->FW_sta_info[i].status = 0;
5305 report_del_sta_event23a(padapter, psta->hwaddr,
5306 65535
5307 );
5308 }
5309 } else {
5310 pmlmeinfo->FW_sta_info[i].retry = 0;
5311 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5312 }
5313 }
5314 }
5315
5316 }
5317}
5318
5319static void survey_timer_hdl(unsigned long data)
5320{
5321 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5322 struct cmd_obj *ph2c;
5323 struct sitesurvey_parm *psurveyPara;
5324 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5325 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5326
5327
5328 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5329 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
5330 pmlmeext->sitesurvey_res.channel_idx++;
5331
5332 if (pmlmeext->scan_abort == true) {
5333 pmlmeext->sitesurvey_res.channel_idx =
5334 pmlmeext->sitesurvey_res.ch_num;
5335 DBG_8723A("%s idx:%d\n", __func__,
5336 pmlmeext->sitesurvey_res.channel_idx);
5337
5338 pmlmeext->scan_abort = false;
5339 }
5340
5341 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
5342 if (!ph2c)
5343 goto exit_survey_timer_hdl;
5344
5345 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm),
5346 GFP_ATOMIC);
5347 if (!psurveyPara) {
5348 kfree(ph2c);
5349 goto exit_survey_timer_hdl;
5350 }
5351
5352 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
5353 GEN_CMD_CODE(_SiteSurvey));
5354 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
5355 }
5356
5357exit_survey_timer_hdl:
5358 return;
5359}
5360
5361static void link_timer_hdl(unsigned long data)
5362{
5363 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5364
5365
5366
5367 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5368 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5369
5370
5371 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5372 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
5373 pmlmeinfo->state = MSR_NOLINK;
5374 report_join_res23a(padapter, -3);
5375 } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5376
5377 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5378
5379
5380 pmlmeinfo->state = 0;
5381 report_join_res23a(padapter, -1);
5382 return;
5383
5384
5385
5386
5387
5388
5389 }
5390
5391 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
5392 pmlmeinfo->auth_seq = 1;
5393 issue_auth(padapter, NULL, 0);
5394 set_link_timer(pmlmeext, REAUTH_TO);
5395 } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5396
5397 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5398 pmlmeinfo->state = MSR_NOLINK;
5399 report_join_res23a(padapter, -2);
5400 return;
5401 }
5402
5403 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
5404 issue_assocreq(padapter);
5405 set_link_timer(pmlmeext, REASSOC_TO);
5406 }
5407
5408 return;
5409}
5410
5411static void addba_timer_hdl(unsigned long data)
5412{
5413 struct sta_info *psta = (struct sta_info *)data;
5414 struct ht_priv *phtpriv;
5415
5416 if (!psta)
5417 return;
5418
5419 phtpriv = &psta->htpriv;
5420
5421 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5422 if (phtpriv->candidate_tid_bitmap)
5423 phtpriv->candidate_tid_bitmap = 0x0;
5424 }
5425}
5426
5427void init_addba_retry_timer23a(struct sta_info *psta)
5428{
5429 setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
5430 (unsigned long)psta);
5431}
5432
5433void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
5434{
5435 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5436
5437 setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
5438 (unsigned long)padapter);
5439
5440 setup_timer(&pmlmeext->link_timer, link_timer_hdl,
5441 (unsigned long)padapter);
5442}
5443
5444int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5445{
5446 return H2C_SUCCESS;
5447}
5448
5449int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5450{
5451 enum nl80211_iftype type;
5452 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5453 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5454 const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5455
5456 switch (psetop->mode) {
5457 case NL80211_IFTYPE_P2P_GO:
5458 case NL80211_IFTYPE_AP:
5459 pmlmeinfo->state = MSR_AP;
5460 type = MSR_AP;
5461 break;
5462 case NL80211_IFTYPE_P2P_CLIENT:
5463 case NL80211_IFTYPE_STATION:
5464
5465 pmlmeinfo->state &= ~(BIT(0)|BIT(1));
5466
5467 pmlmeinfo->state |= MSR_INFRA;
5468 type = MSR_INFRA;
5469 break;
5470 case NL80211_IFTYPE_ADHOC:
5471 type = MSR_ADHOC;
5472 break;
5473 default:
5474 type = MSR_NOLINK;
5475 break;
5476 }
5477
5478 hw_var_set_opmode(padapter, type);
5479
5480
5481 return H2C_SUCCESS;
5482}
5483
5484int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5485{
5486 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5487 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5488 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5489 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5490
5491
5492 if (pparm->ifmode == NL80211_IFTYPE_AP ||
5493 pparm->ifmode == NL80211_IFTYPE_P2P_GO) {
5494#ifdef CONFIG_8723AU_AP_MODE
5495 if (pmlmeinfo->state == MSR_AP) {
5496
5497 return H2C_SUCCESS;
5498 }
5499#endif
5500 }
5501
5502
5503 if (pparm->ifmode == NL80211_IFTYPE_ADHOC) {
5504 rtw_joinbss_reset23a(padapter);
5505
5506 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5507 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5508 pmlmeinfo->ERP_enable = 0;
5509 pmlmeinfo->WMM_enable = 0;
5510 pmlmeinfo->HT_enable = 0;
5511 pmlmeinfo->HT_caps_enable = 0;
5512 pmlmeinfo->HT_info_enable = 0;
5513
5514
5515 rtl8723a_odm_support_ability_backup(padapter);
5516
5517 rtl8723a_odm_support_ability_clr(padapter,
5518 DYNAMIC_FUNC_DISABLE);
5519
5520
5521 del_timer_sync(&pmlmeext->link_timer);
5522
5523
5524 flush_all_cam_entry23a(padapter);
5525
5526 if (pparm->IELength > MAX_IE_SZ)
5527 return H2C_PARAMETERS_ERROR;
5528
5529 memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
5530
5531 start_create_ibss(padapter);
5532 }
5533
5534 return H2C_SUCCESS;
5535}
5536
5537int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5538{
5539 struct registry_priv *pregpriv = &padapter->registrypriv;
5540 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5541 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5542 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5543 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5544 struct ieee80211_ht_operation *pht_info;
5545 u32 i;
5546 u8 *p;
5547
5548
5549
5550
5551 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5552 if (pmlmeinfo->state & MSR_INFRA)
5553 issue_deauth_ex(padapter, pnetwork->MacAddress,
5554 WLAN_REASON_DEAUTH_LEAVING, 5, 100);
5555
5556 pmlmeinfo->state = MSR_NOLINK;
5557
5558
5559 flush_all_cam_entry23a(padapter);
5560
5561 del_timer_sync(&pmlmeext->link_timer);
5562
5563
5564 rtl8723a_set_media_status(padapter, MSR_INFRA);
5565
5566 hw_var_set_mlme_disconnect(padapter);
5567 }
5568
5569 rtw_joinbss_reset23a(padapter);
5570
5571 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5572 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5573 pmlmeinfo->ERP_enable = 0;
5574 pmlmeinfo->WMM_enable = 0;
5575 pmlmeinfo->HT_enable = 0;
5576 pmlmeinfo->HT_caps_enable = 0;
5577 pmlmeinfo->HT_info_enable = 0;
5578 pmlmeinfo->bwmode_updated = false;
5579
5580
5581 if (pparm->IELength > MAX_IE_SZ)
5582 return H2C_PARAMETERS_ERROR;
5583
5584 memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
5585
5586
5587
5588
5589
5590 for (i = 0; i < pnetwork->IELength;) {
5591 p = pnetwork->IEs + i;
5592
5593 switch (p[0]) {
5594 case WLAN_EID_VENDOR_SPECIFIC:
5595 if (!memcmp(p + 2, WMM_OUI23A, 4))
5596 pmlmeinfo->WMM_enable = 1;
5597 break;
5598
5599 case WLAN_EID_HT_CAPABILITY:
5600 pmlmeinfo->HT_caps_enable = 1;
5601 break;
5602
5603 case WLAN_EID_HT_OPERATION:
5604 pmlmeinfo->HT_info_enable = 1;
5605
5606
5607
5608 pht_info = (struct ieee80211_ht_operation *)(p + 2);
5609
5610 if (pregpriv->cbw40_enable &&
5611 (pht_info->ht_param &
5612 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
5613
5614 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
5615 switch (pht_info->ht_param &
5616 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
5617 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
5618 pmlmeext->cur_ch_offset =
5619 HAL_PRIME_CHNL_OFFSET_LOWER;
5620 break;
5621
5622 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
5623 pmlmeext->cur_ch_offset =
5624 HAL_PRIME_CHNL_OFFSET_UPPER;
5625 break;
5626
5627 default:
5628 pmlmeext->cur_ch_offset =
5629 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5630 break;
5631 }
5632
5633 DBG_8723A("set ch/bw before connected\n");
5634 }
5635 break;
5636
5637 default:
5638 break;
5639 }
5640
5641 i += (p[1] + 2);
5642 }
5643
5644 hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
5645 hw_var_set_mlme_join(padapter, 0);
5646
5647
5648 del_timer_sync(&pmlmeext->link_timer);
5649
5650 start_clnt_join(padapter);
5651
5652 return H2C_SUCCESS;
5653}
5654
5655int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5656{
5657 const struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5658 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5659 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5660 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5661
5662 if (is_client_associated_to_ap23a(padapter)) {
5663 issue_deauth_ex(padapter, pnetwork->MacAddress,
5664 WLAN_REASON_DEAUTH_LEAVING,
5665 param->deauth_timeout_ms/100, 100);
5666 }
5667
5668
5669
5670
5671
5672 hw_var_set_mlme_disconnect(padapter);
5673 hw_var_set_bssid(padapter, null_addr);
5674
5675
5676 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
5677
5678 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC ||
5679 (pmlmeinfo->state & 0x03) == MSR_AP)
5680 rtl8723a_set_bcn_func(padapter, 0);
5681
5682
5683 rtl8723a_set_media_status(padapter, MSR_INFRA);
5684
5685 pmlmeinfo->state = MSR_NOLINK;
5686
5687
5688 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5689 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5690
5691 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5692 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5693
5694 flush_all_cam_entry23a(padapter);
5695
5696 del_timer_sync(&pmlmeext->link_timer);
5697
5698 rtw_free_uc_swdec_pending_queue23a(padapter);
5699
5700 return H2C_SUCCESS;
5701}
5702
5703static int
5704rtw_scan_ch_decision(struct rtw_adapter *padapter,
5705 struct rtw_ieee80211_channel *out, u32 out_num,
5706 const struct rtw_ieee80211_channel *in, u32 in_num)
5707{
5708 int i, j;
5709 int scan_ch_num = 0;
5710 int set_idx;
5711 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5712
5713
5714 memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5715
5716
5717 j = 0;
5718 for (i = 0;i<in_num;i++) {
5719 if (in[i].hw_value &&
5720 !(in[i].flags & IEEE80211_CHAN_DISABLED) &&
5721 (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set,
5722 in[i].hw_value)) >= 0) {
5723 memcpy(&out[j], &in[i],
5724 sizeof(struct rtw_ieee80211_channel));
5725
5726 if (pmlmeext->channel_set[set_idx].ScanType ==
5727 SCAN_PASSIVE)
5728 out[j].flags &= IEEE80211_CHAN_NO_IR;
5729
5730 j++;
5731 }
5732 if (j>= out_num)
5733 break;
5734 }
5735
5736
5737 if (j == 0) {
5738 for (i = 0;i<pmlmeext->max_chan_nums;i++) {
5739 out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
5740
5741 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5742 out[i].flags &= IEEE80211_CHAN_NO_IR;
5743
5744 j++;
5745 }
5746 }
5747
5748 if (padapter->setband == GHZ_24) {
5749 for (i = 0; i < j ; i++) {
5750 if (out[i].hw_value > 35)
5751 memset(&out[i], 0,
5752 sizeof(struct rtw_ieee80211_channel));
5753 else
5754 scan_ch_num++;
5755 }
5756 j = scan_ch_num;
5757 } else if (padapter->setband == GHZ_50) {
5758 for (i = 0; i < j ; i++) {
5759 if (out[i].hw_value > 35) {
5760 memcpy(&out[scan_ch_num++], &out[i],
5761 sizeof(struct rtw_ieee80211_channel));
5762 }
5763 }
5764 j = scan_ch_num;
5765 } else
5766 {}
5767
5768 return j;
5769}
5770
5771int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5772{
5773 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5774 const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
5775 u8 bdelayscan = false;
5776 u32 initialgain;
5777 u32 i;
5778
5779 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5780 pmlmeext->sitesurvey_res.state = SCAN_START;
5781 pmlmeext->sitesurvey_res.bss_cnt = 0;
5782 pmlmeext->sitesurvey_res.channel_idx = 0;
5783
5784 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5785 if (pparm->ssid[i].ssid_len) {
5786 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
5787 pparm->ssid[i].ssid,
5788 IEEE80211_MAX_SSID_LEN);
5789 pmlmeext->sitesurvey_res.ssid[i].ssid_len =
5790 pparm->ssid[i].ssid_len;
5791 } else {
5792 pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
5793 }
5794 }
5795
5796 pmlmeext->sitesurvey_res.ch_num =
5797 rtw_scan_ch_decision(padapter,
5798 pmlmeext->sitesurvey_res.ch,
5799 RTW_CHANNEL_SCAN_AMOUNT,
5800 pparm->ch, pparm->ch_num);
5801
5802 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5803
5804
5805 if (is_client_associated_to_ap23a(padapter)) {
5806 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5807
5808
5809
5810 if (rtw_get_oper_ch23a(padapter) !=
5811 pmlmeext->cur_channel)
5812 SelectChannel23a(padapter,
5813 pmlmeext->cur_channel);
5814
5815 issue_nulldata23a(padapter, NULL, 1, 3, 500);
5816
5817 bdelayscan = true;
5818 }
5819
5820 if (bdelayscan) {
5821
5822 set_survey_timer(pmlmeext, 50);
5823 return H2C_SUCCESS;
5824 }
5825 }
5826
5827 if (pmlmeext->sitesurvey_res.state == SCAN_START ||
5828 pmlmeext->sitesurvey_res.state == SCAN_TXNULL) {
5829
5830 rtl8723a_odm_support_ability_backup(padapter);
5831 rtl8723a_odm_support_ability_clr(padapter,
5832 DYNAMIC_FUNC_DISABLE);
5833
5834
5835
5836 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
5837 initialgain = 0x30;
5838 else
5839 initialgain = 0x1E;
5840
5841 rtl8723a_set_initial_gain(padapter, initialgain);
5842
5843
5844 rtl8723a_set_media_status(padapter, MSR_NOLINK);
5845
5846 rtl8723a_mlme_sitesurvey(padapter, 1);
5847
5848 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5849 }
5850
5851 rtw_site_survey(padapter);
5852
5853 return H2C_SUCCESS;
5854}
5855
5856int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5857{
5858 const struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
5859 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5860 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5861
5862 if (pparm->mode < 4)
5863 pmlmeinfo->auth_algo = pparm->mode;
5864
5865 return H2C_SUCCESS;
5866}
5867
5868int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5869{
5870 unsigned short ctrl;
5871 const struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
5872 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5873 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5874 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5875
5876
5877 if (pparm->set_tx)
5878 pmlmeinfo->key_index = pparm->keyid;
5879
5880
5881 ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid;
5882
5883 DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 "
5884 "WEP104-5 TKIP-2 AES-4) keyid:%d\n",
5885 pparm->algorithm, pparm->keyid);
5886 rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
5887
5888
5889 rtl8723a_on_rcr_am(padapter);
5890
5891 return H2C_SUCCESS;
5892}
5893
5894int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5895{
5896 u16 ctrl = 0;
5897 u8 cam_id;
5898 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5899 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5900 const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915 cam_id = 4;
5916
5917 DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 "
5918 "WEP104-5 TKIP-2 AES-4) camid:%d\n",
5919 pparm->algorithm, cam_id);
5920 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
5921 struct sta_info *psta;
5922 struct sta_priv *pstapriv = &padapter->stapriv;
5923
5924 if (pparm->algorithm == 0) {
5925 clear_cam_entry23a(padapter, pparm->id);
5926 return H2C_SUCCESS_RSP;
5927 }
5928
5929 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
5930 if (psta) {
5931 ctrl = BIT(15) | (pparm->algorithm << 2);
5932
5933 DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm "
5934 "=%d\n", pparm->algorithm);
5935
5936 if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) {
5937 DBG_8723A("r871x_set_stakey_hdl23a():set_stakey"
5938 " failed, mac_id(aid) =%d\n",
5939 psta->mac_id);
5940 return H2C_REJECTED;
5941 }
5942
5943
5944
5945 cam_id = psta->mac_id + 3;
5946
5947 DBG_8723A("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, "
5948 "cam_entry =%d\n", pparm->addr[0],
5949 pparm->addr[1], pparm->addr[2],
5950 pparm->addr[3], pparm->addr[4],
5951 pparm->addr[5], cam_id);
5952
5953 rtl8723a_cam_write(padapter, cam_id, ctrl,
5954 pparm->addr, pparm->key);
5955
5956 return H2C_SUCCESS_RSP;
5957 } else {
5958 DBG_8723A("r871x_set_stakey_hdl23a(): sta has been "
5959 "free\n");
5960 return H2C_REJECTED;
5961 }
5962 }
5963
5964
5965
5966 if (pparm->algorithm == 0) {
5967 clear_cam_entry23a(padapter, pparm->id);
5968 return H2C_SUCCESS;
5969 }
5970
5971 ctrl = BIT(15) | (pparm->algorithm << 2);
5972
5973 rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5974
5975 pmlmeinfo->enc_algo = pparm->algorithm;
5976
5977 return H2C_SUCCESS;
5978}
5979
5980int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5981{
5982 const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
5983 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5984 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5985 struct sta_info *psta;
5986
5987 psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
5988
5989 if (!psta)
5990 return H2C_SUCCESS;
5991
5992 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
5993 pmlmeinfo->HT_enable) ||
5994 (pmlmeinfo->state & 0x03) == MSR_AP) {
5995 issue_action_BA23a(padapter, pparm->addr,
5996 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5997 mod_timer(&psta->addba_retry_timer,
5998 jiffies + msecs_to_jiffies(ADDBA_TO));
5999 } else
6000 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
6001
6002 return H2C_SUCCESS;
6003}
6004
6005int set_tx_beacon_cmd23a(struct rtw_adapter *padapter)
6006{
6007 struct cmd_obj *ph2c;
6008 struct Tx_Beacon_param *ptxBeacon_parm;
6009 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6010 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6011 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6012 u8 res = _SUCCESS;
6013 int len_diff = 0;
6014
6015 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
6016 if (!ph2c) {
6017 res = _FAIL;
6018 goto exit;
6019 }
6020
6021 ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
6022 if (!ptxBeacon_parm) {
6023 kfree(ph2c);
6024 res = _FAIL;
6025 goto exit;
6026 }
6027
6028 memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
6029 sizeof(struct wlan_bssid_ex));
6030
6031 len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs,
6032 ptxBeacon_parm->network.IELength,
6033 pmlmeinfo->hidden_ssid_mode);
6034 ptxBeacon_parm->network.IELength += len_diff;
6035
6036 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm,
6037 GEN_CMD_CODE(_TX_Beacon));
6038
6039 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
6040
6041exit:
6042 return res;
6043}
6044
6045int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6046{
6047 u8 evt_code, evt_seq;
6048 u16 evt_sz;
6049 const struct C2HEvent_Header *c2h;
6050 void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf);
6051
6052 c2h = (struct C2HEvent_Header *)pbuf;
6053 evt_sz = c2h->len;
6054 evt_seq = c2h->seq;
6055 evt_code = c2h->ID;
6056
6057
6058 if (evt_code >= MAX_C2HEVT) {
6059 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6060 "Event Code(%d) mismatch!\n", evt_code);
6061 goto _abort_event_;
6062 }
6063
6064
6065 if (wlanevents[evt_code].parmsize != 0 &&
6066 wlanevents[evt_code].parmsize != evt_sz) {
6067 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6068 "Event(%d) Parm Size mismatch (%d vs %d)!\n",
6069 evt_code, wlanevents[evt_code].parmsize, evt_sz);
6070 goto _abort_event_;
6071 }
6072
6073 event_callback = wlanevents[evt_code].event_callback;
6074 event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header));
6075
6076_abort_event_:
6077
6078 return H2C_SUCCESS;
6079}
6080
6081int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6082{
6083 if (!pbuf)
6084 return H2C_PARAMETERS_ERROR;
6085
6086 return H2C_SUCCESS;
6087}
6088
6089int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6090{
6091 if (send_beacon23a(padapter) == _FAIL) {
6092 DBG_8723A("issue_beacon23a, fail!\n");
6093 return H2C_PARAMETERS_ERROR;
6094 }
6095#ifdef CONFIG_8723AU_AP_MODE
6096 else {
6097 struct sta_info *psta_bmc;
6098 struct list_head *plist, *phead, *ptmp;
6099 struct xmit_frame *pxmitframe;
6100 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6101 struct sta_priv *pstapriv = &padapter->stapriv;
6102
6103
6104 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
6105 if (!psta_bmc)
6106 return H2C_SUCCESS;
6107
6108 if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) {
6109 msleep(10);
6110
6111 spin_lock_bh(&pxmitpriv->lock);
6112
6113 phead = get_list_head(&psta_bmc->sleep_q);
6114
6115 list_for_each_safe(plist, ptmp, phead) {
6116 pxmitframe = container_of(plist,
6117 struct xmit_frame,
6118 list);
6119
6120 list_del_init(&pxmitframe->list);
6121
6122 psta_bmc->sleepq_len--;
6123 if (psta_bmc->sleepq_len>0)
6124 pxmitframe->attrib.mdata = 1;
6125 else
6126 pxmitframe->attrib.mdata = 0;
6127
6128 pxmitframe->attrib.triggered = 1;
6129
6130 pxmitframe->attrib.qsel = 0x11;
6131
6132 rtl8723au_hal_xmitframe_enqueue(padapter,
6133 pxmitframe);
6134 }
6135
6136
6137 spin_unlock_bh(&pxmitpriv->lock);
6138 }
6139 }
6140#endif
6141
6142 return H2C_SUCCESS;
6143}
6144
6145int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6146{
6147 const struct set_ch_parm *set_ch_parm;
6148 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6149
6150 if (!pbuf)
6151 return H2C_PARAMETERS_ERROR;
6152
6153 set_ch_parm = (struct set_ch_parm *)pbuf;
6154
6155 DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__,
6156 padapter->pnetdev->name, set_ch_parm->ch,
6157 set_ch_parm->bw, set_ch_parm->ch_offset);
6158
6159 pmlmeext->cur_channel = set_ch_parm->ch;
6160 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6161 pmlmeext->cur_bwmode = set_ch_parm->bw;
6162
6163 set_channel_bwmode23a(padapter, set_ch_parm->ch,
6164 set_ch_parm->ch_offset, set_ch_parm->bw);
6165
6166 return H2C_SUCCESS;
6167}
6168
6169int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6170{
6171 const struct SetChannelPlan_param *setChannelPlan_param;
6172 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6173
6174 if (!pbuf)
6175 return H2C_PARAMETERS_ERROR;
6176
6177 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6178
6179 pmlmeext->max_chan_nums =
6180 init_channel_set(padapter, setChannelPlan_param->channel_plan,
6181 pmlmeext->channel_set);
6182 init_channel_list(padapter, pmlmeext->channel_set,
6183 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6184
6185 return H2C_SUCCESS;
6186}
6187
6188int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6189{
6190 struct LedBlink_param *ledBlink_param;
6191
6192 if (!pbuf)
6193 return H2C_PARAMETERS_ERROR;
6194
6195 ledBlink_param = (struct LedBlink_param *)pbuf;
6196
6197 return H2C_SUCCESS;
6198}
6199
6200int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6201{
6202 return H2C_REJECTED;
6203}
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6222{
6223 return H2C_REJECTED;
6224}
6225