1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3 *
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 *
6 ******************************************************************************/
7 #include <drv_types.h>
8 #include <rtw_wifi_regd.h>
9 #include <hal_btcoex.h>
10 #include <linux/kernel.h>
11 #include <linux/unaligned.h>
12
13 static struct mlme_handler mlme_sta_tbl[] = {
14 {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},
15 {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},
16 {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},
17 {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},
18 {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq},
19 {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp},
20
21 /* below 2 are reserved */
22 {0, "DoReserved", &DoReserved},
23 {0, "DoReserved", &DoReserved},
24 {WIFI_BEACON, "OnBeacon", &OnBeacon},
25 {WIFI_ATIM, "OnATIM", &OnAtim},
26 {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc},
27 {WIFI_AUTH, "OnAuth", &OnAuthClient},
28 {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth},
29 {WIFI_ACTION, "OnAction", &OnAction},
30 {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction},
31 };
32
33 static struct action_handler OnAction_tbl[] = {
34 {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct},
35 {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved},
36 {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved},
37 {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
38 {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
39 {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
40 {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved},
41 {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht},
42 {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
43 {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
44 {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved},
45 {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved},
46 {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved},
47 };
48
49 static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
50
51 /* OUI definitions for the vendor specific IE */
52 unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
53 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
54 unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
55 unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
56 unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
57
58 unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
59 unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
60
61 static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
62
63 /* ChannelPlan definitions */
64 static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
65 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
66 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
67 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
68 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
69 {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
70 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x05, RT_CHANNEL_DOMAIN_2G_GLOBAL , Passive scan CH 12, 13, 14 */
71 {{}, 0}, /* 0x06, RT_CHANNEL_DOMAIN_2G_NULL */
72 };
73
74 static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
75 /* 0x00 ~ 0x1F , Old Define ===== */
76 {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
77 {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
78 {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
79 {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
80 {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
81 {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
82 {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
83 {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
84 {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
85 {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
86 {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
87 {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
88 {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
89 {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
90 {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
91 {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
92 {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
93 {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
94 {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
95 {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
96 {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
97 {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
98 {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
99 {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
100 {0x06}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
101 {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
102 {0x00}, /* 0x1A, */
103 {0x00}, /* 0x1B, */
104 {0x00}, /* 0x1C, */
105 {0x00}, /* 0x1D, */
106 {0x00}, /* 0x1E, */
107 {0x06}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
108 /* 0x20 ~ 0x7F , New Define ===== */
109 {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
110 {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
111 {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
112 {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
113 {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
114 {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
115 {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
116 {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
117 {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
118 {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
119 {0x00}, /* 0x2A, */
120 {0x00}, /* 0x2B, */
121 {0x00}, /* 0x2C, */
122 {0x00}, /* 0x2D, */
123 {0x00}, /* 0x2E, */
124 {0x00}, /* 0x2F, */
125 {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
126 {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
127 {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
128 {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
129 {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
130 {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
131 {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
132 {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
133 {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
134 {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
135 {0x00}, /* 0x3A, */
136 {0x00}, /* 0x3B, */
137 {0x00}, /* 0x3C, */
138 {0x00}, /* 0x3D, */
139 {0x00}, /* 0x3E, */
140 {0x00}, /* 0x3F, */
141 {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
142 {0x05}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */
143 {0x01}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */
144 {0x02}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */
145 {0x02}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */
146 {0x00}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */
147 {0x02}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */
148 {0x00}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */
149 {0x00}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */
150 {0x00}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */
151 {0x00}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */
152 {0x00}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */
153 {0x00}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */
154 {0x02}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */
155 {0x00}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */
156 {0x02}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */
157 {0x00}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */
158 {0x02}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */
159 };
160
161 /* use the combination for max channel numbers */
162 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03};
163
164 /* Search the @param ch in given @param ch_set
165 * @ch_set: the given channel set
166 * @ch: the given channel number
167 *
168 * return the index of channel_num in channel_set, -1 if not found
169 */
rtw_ch_set_search_ch(struct rt_channel_info * ch_set,const u32 ch)170 int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
171 {
172 int i;
173
174 for (i = 0; ch_set[i].ChannelNum != 0; i++) {
175 if (ch == ch_set[i].ChannelNum)
176 break;
177 }
178
179 if (i >= ch_set[i].ChannelNum)
180 return -1;
181 return i;
182 }
183
184 /* Following are the initialization functions for WiFi MLME */
185
init_hw_mlme_ext(struct adapter * padapter)186 int init_hw_mlme_ext(struct adapter *padapter)
187 {
188 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
189
190 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
191 return _SUCCESS;
192 }
193
init_mlme_default_rate_set(struct adapter * padapter)194 void init_mlme_default_rate_set(struct adapter *padapter)
195 {
196 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
197
198 unsigned char mixed_datarate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_, 0xff};
199 unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
200 unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
201
202 memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
203 memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
204
205 memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));
206 }
207
init_mlme_ext_priv_value(struct adapter * padapter)208 static void init_mlme_ext_priv_value(struct adapter *padapter)
209 {
210 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
211 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
212
213 atomic_set(&pmlmeext->event_seq, 0);
214 pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
215 pmlmeext->sa_query_seq = 0;
216 pmlmeext->mgnt_80211w_IPN = 0;
217 pmlmeext->mgnt_80211w_IPN_rx = 0;
218 pmlmeext->cur_channel = padapter->registrypriv.channel;
219 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
220 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
221
222 pmlmeext->retry = 0;
223
224 pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
225
226 init_mlme_default_rate_set(padapter);
227
228 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
229 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
230 pmlmeext->sitesurvey_res.channel_idx = 0;
231 pmlmeext->sitesurvey_res.bss_cnt = 0;
232 pmlmeext->scan_abort = false;
233
234 pmlmeinfo->state = WIFI_FW_NULL_STATE;
235 pmlmeinfo->reauth_count = 0;
236 pmlmeinfo->reassoc_count = 0;
237 pmlmeinfo->link_count = 0;
238 pmlmeinfo->auth_seq = 0;
239 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
240 pmlmeinfo->key_index = 0;
241 pmlmeinfo->iv = 0;
242
243 pmlmeinfo->enc_algo = _NO_PRIVACY_;
244 pmlmeinfo->authModeToggle = 0;
245
246 memset(pmlmeinfo->chg_txt, 0, 128);
247
248 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
249 pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
250
251 pmlmeinfo->dialogToken = 0;
252
253 pmlmeext->action_public_rxseq = 0xffff;
254 pmlmeext->action_public_dialog_token = 0xff;
255 }
256
has_channel(struct rt_channel_info * channel_set,u8 chanset_size,u8 chan)257 static int has_channel(struct rt_channel_info *channel_set,
258 u8 chanset_size,
259 u8 chan)
260 {
261 int i;
262
263 for (i = 0; i < chanset_size; i++)
264 if (channel_set[i].ChannelNum == chan)
265 return 1;
266
267 return 0;
268 }
269
init_channel_list(struct adapter * padapter,struct rt_channel_info * channel_set,u8 chanset_size,struct p2p_channels * channel_list)270 static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
271 u8 chanset_size,
272 struct p2p_channels *channel_list)
273 {
274
275 static const struct p2p_oper_class_map op_class[] = {
276 { IEEE80211G, 81, 1, 13, 1, BW20 },
277 { IEEE80211G, 82, 14, 14, 1, BW20 },
278 { IEEE80211A, 115, 36, 48, 4, BW20 },
279 { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
280 { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
281 { IEEE80211A, 124, 149, 161, 4, BW20 },
282 { IEEE80211A, 125, 149, 169, 4, BW20 },
283 { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
284 { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
285 { -1, 0, 0, 0, 0, BW20 }
286 };
287
288 int cla, op;
289
290 cla = 0;
291
292 for (op = 0; op_class[op].op_class; op++) {
293 u8 ch;
294 const struct p2p_oper_class_map *o = &op_class[op];
295 struct p2p_reg_class *reg = NULL;
296
297 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
298 if (!has_channel(channel_set, chanset_size, ch))
299 continue;
300
301 if ((padapter->registrypriv.ht_enable == 0) && (o->inc == 8))
302 continue;
303
304 if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) &&
305 ((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))
306 continue;
307
308 if (!reg) {
309 reg = &channel_list->reg_class[cla];
310 cla++;
311 reg->reg_class = o->op_class;
312 reg->channels = 0;
313 }
314 reg->channel[reg->channels] = ch;
315 reg->channels++;
316 }
317 }
318 channel_list->reg_classes = cla;
319
320 }
321
init_channel_set(struct adapter * padapter,u8 ChannelPlan,struct rt_channel_info * channel_set)322 static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
323 {
324 u8 index, chanset_size = 0;
325 u8 b2_4GBand = false;
326 u8 Index2G = 0;
327
328 memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM);
329
330 if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
331 return chanset_size;
332
333 if (is_supported_24g(padapter->registrypriv.wireless_mode)) {
334 b2_4GBand = true;
335 if (ChannelPlan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
336 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
337 else
338 Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
339 }
340
341 if (b2_4GBand) {
342 for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
343 channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
344
345 if ((ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN) ||/* Channel 1~11 is active, and 12~14 is passive */
346 (ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_NULL)) {
347 if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
348 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
349 else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14))
350 channel_set[chanset_size].ScanType = SCAN_PASSIVE;
351 } else if (ChannelPlan == RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ||
352 Index2G == RT_CHANNEL_DOMAIN_2G_WORLD) { /* channel 12~13, passive scan */
353 if (channel_set[chanset_size].ChannelNum <= 11)
354 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
355 else
356 channel_set[chanset_size].ScanType = SCAN_PASSIVE;
357 } else
358 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
359
360 chanset_size++;
361 }
362 }
363
364 return chanset_size;
365 }
366
init_mlme_ext_timer(struct adapter * padapter)367 static void init_mlme_ext_timer(struct adapter *padapter)
368 {
369 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
370
371 timer_setup(&pmlmeext->survey_timer, survey_timer_hdl, 0);
372 timer_setup(&pmlmeext->link_timer, link_timer_hdl, 0);
373 timer_setup(&pmlmeext->sa_query_timer, sa_query_timer_hdl, 0);
374 }
375
init_mlme_ext_priv(struct adapter * padapter)376 void init_mlme_ext_priv(struct adapter *padapter)
377 {
378 struct registry_priv *pregistrypriv = &padapter->registrypriv;
379 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
380 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
381 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
382
383 pmlmeext->padapter = padapter;
384
385 /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */
386
387 init_mlme_ext_priv_value(padapter);
388 pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req;
389
390 init_mlme_ext_timer(padapter);
391
392 init_mlme_ap_info(padapter);
393
394 pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
395 init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
396 pmlmeext->last_scan_time = 0;
397 pmlmeext->chan_scan_time = SURVEY_TO;
398 pmlmeext->mlmeext_init = true;
399 pmlmeext->active_keep_alive_check = true;
400
401 #ifdef DBG_FIXED_CHAN
402 pmlmeext->fixed_chan = 0xFF;
403 #endif
404 }
405
free_mlme_ext_priv(struct mlme_ext_priv * pmlmeext)406 void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
407 {
408 struct adapter *padapter = pmlmeext->padapter;
409
410 if (!padapter)
411 return;
412
413 if (padapter->bDriverStopped) {
414 timer_delete_sync(&pmlmeext->survey_timer);
415 timer_delete_sync(&pmlmeext->link_timer);
416 /* timer_delete_sync(&pmlmeext->ADDBA_timer); */
417 }
418 }
419
_mgt_dispatcher(struct adapter * padapter,struct mlme_handler * ptable,union recv_frame * precv_frame)420 static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
421 {
422 u8 *pframe = precv_frame->u.hdr.rx_data;
423
424 if (ptable->func) {
425 /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
426 if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
427 !is_broadcast_ether_addr(GetAddr1Ptr(pframe)))
428 return;
429
430 ptable->func(padapter, precv_frame);
431 }
432 }
433
mgt_dispatcher(struct adapter * padapter,union recv_frame * precv_frame)434 void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
435 {
436 int index;
437 struct mlme_handler *ptable;
438 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
439 u8 *pframe = precv_frame->u.hdr.rx_data;
440 struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
441
442 if (GetFrameType(pframe) != WIFI_MGT_TYPE)
443 return;
444
445 /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
446 if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
447 !is_broadcast_ether_addr(GetAddr1Ptr(pframe))) {
448 return;
449 }
450
451 ptable = mlme_sta_tbl;
452
453 index = GetFrameSubType(pframe) >> 4;
454
455 if (index >= ARRAY_SIZE(mlme_sta_tbl))
456 return;
457
458 ptable += index;
459
460 if (psta) {
461 if (GetRetry(pframe)) {
462 if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
463 /* drop the duplicate management frame */
464 return;
465 }
466 }
467 psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
468 }
469
470 switch (GetFrameSubType(pframe)) {
471 case WIFI_AUTH:
472 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
473 ptable->func = &OnAuth;
474 else
475 ptable->func = &OnAuthClient;
476 fallthrough;
477 case WIFI_ASSOCREQ:
478 case WIFI_REASSOCREQ:
479 _mgt_dispatcher(padapter, ptable, precv_frame);
480 break;
481 case WIFI_PROBEREQ:
482 _mgt_dispatcher(padapter, ptable, precv_frame);
483 break;
484 case WIFI_BEACON:
485 _mgt_dispatcher(padapter, ptable, precv_frame);
486 break;
487 case WIFI_ACTION:
488 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */
489 _mgt_dispatcher(padapter, ptable, precv_frame);
490 break;
491 default:
492 _mgt_dispatcher(padapter, ptable, precv_frame);
493 break;
494 }
495 }
496
497 /* Following are the callback functions for each subtype of the management frames */
498
OnProbeReq(struct adapter * padapter,union recv_frame * precv_frame)499 unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
500 {
501 unsigned int ielen;
502 unsigned char *p;
503 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
504 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
505 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
506 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
507 u8 *pframe = precv_frame->u.hdr.rx_data;
508 uint len = precv_frame->u.hdr.len;
509 u8 is_valid_p2p_probereq = false;
510
511 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
512 return _SUCCESS;
513
514 if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
515 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
516 return _SUCCESS;
517 }
518
519 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_SSID, (int *)&ielen,
520 len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
521
522
523 /* check (wildcard) SSID */
524 if (p) {
525 if (is_valid_p2p_probereq)
526 goto _issue_probersp;
527
528 if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->ssid.ssid, cur->ssid.ssid_length))
529 || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
530 )
531 return _SUCCESS;
532
533 _issue_probersp:
534 if ((check_fwstate(pmlmepriv, _FW_LINKED) &&
535 pmlmepriv->cur_network.join_res) ||
536 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
537 issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
538 }
539
540 return _SUCCESS;
541
542 }
543
OnProbeRsp(struct adapter * padapter,union recv_frame * precv_frame)544 unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
545 {
546 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
547
548 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
549 report_survey_event(padapter, precv_frame);
550 return _SUCCESS;
551 }
552
553 return _SUCCESS;
554
555 }
556
OnBeacon(struct adapter * padapter,union recv_frame * precv_frame)557 unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
558 {
559 int cam_idx;
560 struct sta_info *psta;
561 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
562 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
563 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
564 struct sta_priv *pstapriv = &padapter->stapriv;
565 u8 *pframe = precv_frame->u.hdr.rx_data;
566 uint len = precv_frame->u.hdr.len;
567 struct wlan_bssid_ex *pbss;
568 int ret = _SUCCESS;
569 u8 *p = NULL;
570 u32 ielen = 0;
571
572 p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_);
573 if (p && ielen > 0) {
574 if (p + 2 + ielen < pframe + len) {
575 if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D))
576 /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */
577 *(p + 1) = ielen - 1;
578 }
579 }
580
581 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
582 report_survey_event(padapter, precv_frame);
583 return _SUCCESS;
584 }
585
586 if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
587 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
588 /* we should update current network before auth, or some IE is wrong */
589 pbss = kmalloc_obj(*pbss, GFP_ATOMIC);
590 if (pbss) {
591 if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
592 update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
593 rtw_get_bcn_info(&(pmlmepriv->cur_network));
594 }
595 kfree(pbss);
596 }
597
598 /* check the vendor of the assoc AP */
599 pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
600
601 /* update TSF Value */
602 update_TSF(pmlmeext, pframe, len);
603
604 /* reset for adaptive_early_32k */
605 pmlmeext->adaptive_tsf_done = false;
606 pmlmeext->DrvBcnEarly = 0xff;
607 pmlmeext->DrvBcnTimeOut = 0xff;
608 pmlmeext->bcn_cnt = 0;
609 memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt));
610 memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio));
611
612 /* start auth */
613 start_clnt_auth(padapter);
614
615 return _SUCCESS;
616 }
617
618 if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
619 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
620 if (psta) {
621 ret = rtw_check_bcn_info(padapter, pframe, len);
622 if (!ret) {
623 netdev_dbg(padapter->pnetdev,
624 "ap has changed, disconnect now\n");
625 receive_disconnect(padapter,
626 pmlmeinfo->network.mac_address, 0);
627 return _SUCCESS;
628 }
629 /* update WMM, ERP in the beacon */
630 /* todo: the timer is used instead of the number of the beacon received */
631 if ((sta_rx_pkts(psta) & 0xf) == 0)
632 update_beacon_info(padapter, pframe, len, psta);
633
634 adaptive_early_32k(pmlmeext, pframe, len);
635 }
636 } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
637 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
638 if (psta) {
639 /* update WMM, ERP in the beacon */
640 /* todo: the timer is used instead of the number of the beacon received */
641 if ((sta_rx_pkts(psta) & 0xf) == 0)
642 update_beacon_info(padapter, pframe, len, psta);
643 } else {
644 /* allocate a new CAM entry for IBSS station */
645 cam_idx = allocate_fw_sta_entry(padapter);
646 if (cam_idx == NUM_STA)
647 goto _END_ONBEACON_;
648
649 /* get supported rate */
650 if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
651 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
652 goto _END_ONBEACON_;
653 }
654
655 /* update TSF Value */
656 update_TSF(pmlmeext, pframe, len);
657
658 /* report sta add event */
659 report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
660 }
661 }
662 }
663
664 _END_ONBEACON_:
665
666 return _SUCCESS;
667
668 }
669
OnAuth(struct adapter * padapter,union recv_frame * precv_frame)670 unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
671 {
672 unsigned int auth_mode, seq, ie_len;
673 unsigned char *sa, *p;
674 u16 algorithm;
675 int status;
676 static struct sta_info stat;
677 struct sta_info *pstat = NULL;
678 struct sta_priv *pstapriv = &padapter->stapriv;
679 struct security_priv *psecuritypriv = &padapter->securitypriv;
680 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
681 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
682 u8 *pframe = precv_frame->u.hdr.rx_data;
683 uint len = precv_frame->u.hdr.len;
684 u8 offset = 0;
685
686 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
687 return _FAIL;
688
689 sa = GetAddr2Ptr(pframe);
690
691 auth_mode = psecuritypriv->dot11AuthAlgrthm;
692
693 if (GetPrivacy(pframe)) {
694 u8 *iv;
695 struct rx_pkt_attrib *prxattrib = &(precv_frame->u.hdr.attrib);
696
697 prxattrib->hdrlen = WLAN_HDR_A3_LEN;
698 prxattrib->encrypt = _WEP40_;
699
700 iv = pframe+prxattrib->hdrlen;
701 prxattrib->key_index = ((iv[3]>>6)&0x3);
702
703 prxattrib->iv_len = 4;
704 prxattrib->icv_len = 4;
705
706 rtw_wep_decrypt(padapter, (u8 *)precv_frame);
707
708 offset = 4;
709 }
710
711 algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
712 seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
713
714 if (auth_mode == 2 &&
715 psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
716 psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
717 auth_mode = 0;
718
719 if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */
720 (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */
721
722 status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
723
724 goto auth_fail;
725 }
726
727 if (rtw_access_ctrl(padapter, sa) == false) {
728 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
729 goto auth_fail;
730 }
731
732 pstat = rtw_get_stainfo(pstapriv, sa);
733 if (!pstat) {
734
735 /* allocate a new one */
736 pstat = rtw_alloc_stainfo(pstapriv, sa);
737 if (!pstat) {
738 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
739 goto auth_fail;
740 }
741
742 pstat->state = WIFI_FW_AUTH_NULL;
743 pstat->auth_seq = 0;
744
745 /* pstat->flags = 0; */
746 /* pstat->capability = 0; */
747 } else {
748
749 spin_lock_bh(&pstapriv->asoc_list_lock);
750 if (list_empty(&pstat->asoc_list) == false) {
751 list_del_init(&pstat->asoc_list);
752 pstapriv->asoc_list_cnt--;
753 if (pstat->expire_to > 0) {
754 /* TODO: STA re_auth within expire_to */
755 }
756 }
757 spin_unlock_bh(&pstapriv->asoc_list_lock);
758
759 if (seq == 1) {
760 /* TODO: STA re_auth and auth timeout */
761 }
762 }
763
764 spin_lock_bh(&pstapriv->auth_list_lock);
765 if (list_empty(&pstat->auth_list)) {
766
767 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
768 pstapriv->auth_list_cnt++;
769 }
770 spin_unlock_bh(&pstapriv->auth_list_lock);
771
772 if (pstat->auth_seq == 0)
773 pstat->expire_to = pstapriv->auth_to;
774
775
776 if ((pstat->auth_seq + 1) != seq) {
777 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
778 goto auth_fail;
779 }
780
781 if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) {
782 if (seq == 1) {
783 pstat->state &= ~WIFI_FW_AUTH_NULL;
784 pstat->state |= WIFI_FW_AUTH_SUCCESS;
785 pstat->expire_to = pstapriv->assoc_to;
786 pstat->authalg = algorithm;
787 } else {
788 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
789 goto auth_fail;
790 }
791 } else { /* shared system or auto authentication */
792 if (seq == 1) {
793 /* prepare for the challenging txt... */
794 memset((void *)pstat->chg_txt, 78, 128);
795
796 pstat->state &= ~WIFI_FW_AUTH_NULL;
797 pstat->state |= WIFI_FW_AUTH_STATE;
798 pstat->authalg = algorithm;
799 } else if (seq == 3) {
800
801 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&ie_len,
802 len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
803
804 if (!p || ie_len <= 0) {
805 status = WLAN_STATUS_CHALLENGE_FAIL;
806 goto auth_fail;
807 }
808
809 if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
810 pstat->state &= (~WIFI_FW_AUTH_STATE);
811 pstat->state |= WIFI_FW_AUTH_SUCCESS;
812 /* challenging txt is correct... */
813 pstat->expire_to = pstapriv->assoc_to;
814 } else {
815 status = WLAN_STATUS_CHALLENGE_FAIL;
816 goto auth_fail;
817 }
818 } else {
819 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
820 goto auth_fail;
821 }
822 }
823
824
825 /* Now, we are going to issue_auth... */
826 pstat->auth_seq = seq + 1;
827
828 issue_auth(padapter, pstat, (unsigned short)(WLAN_STATUS_SUCCESS));
829
830 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
831 pstat->auth_seq = 0;
832
833
834 return _SUCCESS;
835
836 auth_fail:
837
838 if (pstat)
839 rtw_free_stainfo(padapter, pstat);
840
841 pstat = &stat;
842 memset((char *)pstat, '\0', sizeof(stat));
843 pstat->auth_seq = 2;
844 memcpy(pstat->hwaddr, sa, 6);
845
846 issue_auth(padapter, pstat, (unsigned short)status);
847
848 return _FAIL;
849
850 }
851
OnAuthClient(struct adapter * padapter,union recv_frame * precv_frame)852 unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
853 {
854 unsigned int seq, len, status, offset;
855 unsigned char *p;
856 unsigned int go2asoc = 0;
857 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
858 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
859 u8 *pframe = precv_frame->u.hdr.rx_data;
860 uint pkt_len = precv_frame->u.hdr.len;
861
862 /* check A1 matches or not */
863 if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
864 return _SUCCESS;
865
866 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
867 return _SUCCESS;
868
869 offset = (GetPrivacy(pframe)) ? 4 : 0;
870
871 seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
872 status = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
873
874 if (status != 0) {
875 if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
876 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
877 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
878 else
879 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
880 /* pmlmeinfo->reauth_count = 0; */
881 }
882
883 set_link_timer(pmlmeext, 1);
884 goto authclnt_fail;
885 }
886
887 if (seq == 2) {
888 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
889 /* legendary shared system */
890 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&len,
891 pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
892
893 if (!p)
894 goto authclnt_fail;
895
896 memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
897 pmlmeinfo->auth_seq = 3;
898 issue_auth(padapter, NULL, 0);
899 set_link_timer(pmlmeext, REAUTH_TO);
900
901 return _SUCCESS;
902 }
903 /* open system */
904 go2asoc = 1;
905 } else if (seq == 4) {
906 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
907 go2asoc = 1;
908 else
909 goto authclnt_fail;
910 } else {
911 /* this is also illegal */
912 goto authclnt_fail;
913 }
914
915 if (go2asoc) {
916 netdev_dbg(padapter->pnetdev, "auth success, start assoc\n");
917 start_clnt_assoc(padapter);
918 return _SUCCESS;
919 }
920
921 authclnt_fail:
922
923 /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
924
925 return _FAIL;
926
927 }
928
OnAssocReq(struct adapter * padapter,union recv_frame * precv_frame)929 unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
930 {
931 u16 capab_info;
932 struct rtw_ieee802_11_elems elems;
933 struct sta_info *pstat;
934 unsigned char *p, *pos, *wpa_ie;
935 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
936 int i, ie_len, wpa_ie_len, left;
937 unsigned char supportRate[16];
938 int supportRateNum;
939 unsigned short status = WLAN_STATUS_SUCCESS;
940 unsigned short frame_type, ie_offset = 0;
941 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
942 struct security_priv *psecuritypriv = &padapter->securitypriv;
943 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
944 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
945 struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
946 struct sta_priv *pstapriv = &padapter->stapriv;
947 u8 *pframe = precv_frame->u.hdr.rx_data;
948 uint pkt_len = precv_frame->u.hdr.len;
949
950 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
951 return _FAIL;
952
953 frame_type = GetFrameSubType(pframe);
954 if (frame_type == WIFI_ASSOCREQ)
955 ie_offset = _ASOCREQ_IE_OFFSET_;
956 else /* WIFI_REASSOCREQ */
957 ie_offset = _REASOCREQ_IE_OFFSET_;
958
959
960 if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset)
961 return _FAIL;
962
963 pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
964 if (!pstat) {
965 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
966 goto asoc_class2_error;
967 }
968
969 capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
970 /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */
971
972 left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
973 pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
974
975 /* check if this stat has been successfully authenticated/associated */
976 if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
977 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
978 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
979 goto asoc_class2_error;
980 } else {
981 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
982 pstat->state |= WIFI_FW_ASSOC_STATE;
983 }
984 } else {
985 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
986 pstat->state |= WIFI_FW_ASSOC_STATE;
987 }
988
989
990 pstat->capability = capab_info;
991
992 /* now parse all ieee802_11 ie to point to elems */
993 if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
994 !elems.ssid) {
995 status = WLAN_STATUS_CHALLENGE_FAIL;
996 goto OnAssocReqFail;
997 }
998
999 /* now we should check all the fields... */
1000 /* checking SSID */
1001 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SSID, &ie_len,
1002 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1003
1004 if (!p || ie_len == 0) {
1005 /* broadcast ssid, however it is not allowed in assocreq */
1006 status = WLAN_STATUS_CHALLENGE_FAIL;
1007 goto OnAssocReqFail;
1008 } else {
1009 /* check if ssid match */
1010 if (memcmp((void *)(p+2), cur->ssid.ssid, cur->ssid.ssid_length))
1011 status = WLAN_STATUS_CHALLENGE_FAIL;
1012
1013 if (ie_len != cur->ssid.ssid_length)
1014 status = WLAN_STATUS_CHALLENGE_FAIL;
1015 }
1016
1017 if (status != WLAN_STATUS_SUCCESS)
1018 goto OnAssocReqFail;
1019
1020 /* check if the supported rate is ok */
1021 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SUPP_RATES, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1022 if (!p) {
1023 /* use our own rate set as statoin used */
1024 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1025 /* supportRateNum = AP_BSSRATE_LEN; */
1026
1027 status = WLAN_STATUS_CHALLENGE_FAIL;
1028 goto OnAssocReqFail;
1029 } else {
1030 if (ie_len > sizeof(supportRate))
1031 ie_len = sizeof(supportRate);
1032
1033 memcpy(supportRate, p+2, ie_len);
1034 supportRateNum = ie_len;
1035
1036 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_EXT_SUPP_RATES, &ie_len,
1037 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1038 if (p) {
1039
1040 if (supportRateNum + ie_len <= sizeof(supportRate)) {
1041 memcpy(supportRate+supportRateNum, p+2, ie_len);
1042 supportRateNum += ie_len;
1043 }
1044 }
1045 }
1046
1047 /* todo: mask supportRate between AP & STA -> move to update raid */
1048 /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1049
1050 /* update station supportRate */
1051 pstat->bssratelen = supportRateNum;
1052 memcpy(pstat->bssrateset, supportRate, supportRateNum);
1053 update_basic_rate_table_soft_ap(pstat->bssrateset, pstat->bssratelen);
1054
1055 /* check RSN/WPA/WPS */
1056 pstat->dot8021xalg = 0;
1057 pstat->wpa_psk = 0;
1058 pstat->wpa_group_cipher = 0;
1059 pstat->wpa2_group_cipher = 0;
1060 pstat->wpa_pairwise_cipher = 0;
1061 pstat->wpa2_pairwise_cipher = 0;
1062 memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1063 if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1064
1065 int group_cipher = 0, pairwise_cipher = 0;
1066
1067 wpa_ie = elems.rsn_ie;
1068 wpa_ie_len = elems.rsn_ie_len;
1069
1070 if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1071 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1072 pstat->wpa_psk |= BIT(1);
1073
1074 pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1075 pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1076
1077 if (!pstat->wpa2_group_cipher)
1078 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1079
1080 if (!pstat->wpa2_pairwise_cipher)
1081 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1082 } else {
1083 status = WLAN_STATUS_INVALID_IE;
1084 }
1085
1086 } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1087
1088 int group_cipher = 0, pairwise_cipher = 0;
1089
1090 wpa_ie = elems.wpa_ie;
1091 wpa_ie_len = elems.wpa_ie_len;
1092
1093 if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1094 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1095 pstat->wpa_psk |= BIT(0);
1096
1097 pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1098 pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1099
1100 if (!pstat->wpa_group_cipher)
1101 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1102
1103 if (!pstat->wpa_pairwise_cipher)
1104 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1105
1106 } else {
1107 status = WLAN_STATUS_INVALID_IE;
1108 }
1109
1110 } else {
1111 wpa_ie = NULL;
1112 wpa_ie_len = 0;
1113 }
1114
1115 if (status != WLAN_STATUS_SUCCESS)
1116 goto OnAssocReqFail;
1117
1118 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1119 if (!wpa_ie) {
1120 if (elems.wps_ie)
1121 pstat->flags |= WLAN_STA_WPS;
1122 else
1123 pstat->flags |= WLAN_STA_MAYBE_WPS;
1124
1125
1126 /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1127 /* that the selected registrar of AP is _FLASE */
1128 if ((psecuritypriv->wpa_psk > 0)
1129 && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1130 if (pmlmepriv->wps_beacon_ie) {
1131 u8 selected_registrar = 0;
1132
1133 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1134
1135 if (!selected_registrar) {
1136 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1137
1138 goto OnAssocReqFail;
1139 }
1140 }
1141 }
1142
1143 } else {
1144 int copy_len;
1145
1146 if (psecuritypriv->wpa_psk == 0) {
1147 status = WLAN_STATUS_INVALID_IE;
1148
1149 goto OnAssocReqFail;
1150
1151 }
1152
1153 if (elems.wps_ie) {
1154 pstat->flags |= WLAN_STA_WPS;
1155 copy_len = 0;
1156 } else {
1157 copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
1158 }
1159
1160
1161 if (copy_len > 0)
1162 memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1163
1164 }
1165
1166
1167 /* check if there is WMM IE & support WWM-PS */
1168 pstat->flags &= ~WLAN_STA_WME;
1169 pstat->qos_option = 0;
1170 pstat->qos_info = 0;
1171 pstat->has_legacy_ac = true;
1172 pstat->uapsd_vo = 0;
1173 pstat->uapsd_vi = 0;
1174 pstat->uapsd_be = 0;
1175 pstat->uapsd_bk = 0;
1176 if (pmlmepriv->qospriv.qos_option) {
1177 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1178 for (;;) {
1179 p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1180 if (!p)
1181 break;
1182
1183 if (memcmp(p+2, WMM_IE, 6)) {
1184 p = p + ie_len + 2;
1185 continue;
1186 }
1187
1188 pstat->flags |= WLAN_STA_WME;
1189
1190 pstat->qos_option = 1;
1191 pstat->qos_info = *(p+8);
1192
1193 pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1194
1195 if ((pstat->qos_info&0xf) != 0xf)
1196 pstat->has_legacy_ac = true;
1197 else
1198 pstat->has_legacy_ac = false;
1199
1200 if (pstat->qos_info&0xf) {
1201 if (pstat->qos_info&BIT(0))
1202 pstat->uapsd_vo = BIT(0)|BIT(1);
1203 else
1204 pstat->uapsd_vo = 0;
1205
1206 if (pstat->qos_info&BIT(1))
1207 pstat->uapsd_vi = BIT(0)|BIT(1);
1208 else
1209 pstat->uapsd_vi = 0;
1210
1211 if (pstat->qos_info&BIT(2))
1212 pstat->uapsd_bk = BIT(0)|BIT(1);
1213 else
1214 pstat->uapsd_bk = 0;
1215
1216 if (pstat->qos_info&BIT(3))
1217 pstat->uapsd_be = BIT(0)|BIT(1);
1218 else
1219 pstat->uapsd_be = 0;
1220
1221 }
1222
1223 break;
1224 }
1225 }
1226
1227 /* save HT capabilities in the sta object */
1228 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1229 if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
1230 pstat->flags |= WLAN_STA_HT;
1231
1232 pstat->flags |= WLAN_STA_WME;
1233
1234 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
1235
1236 } else
1237 pstat->flags &= ~WLAN_STA_HT;
1238
1239
1240 if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) {
1241 status = WLAN_STATUS_CHALLENGE_FAIL;
1242 goto OnAssocReqFail;
1243 }
1244
1245
1246 if ((pstat->flags & WLAN_STA_HT) &&
1247 ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1248 (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
1249 /* status = WLAN_STATUS_CIPHER_SUITE_REJECTED; */
1250 /* goto OnAssocReqFail; */
1251 }
1252 pstat->flags |= WLAN_STA_NONERP;
1253 for (i = 0; i < pstat->bssratelen; i++) {
1254 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1255 pstat->flags &= ~WLAN_STA_NONERP;
1256 break;
1257 }
1258 }
1259
1260 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1261 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1262 else
1263 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1264
1265 /* TODO: identify_proprietary_vendor_ie(); */
1266 /* Realtek proprietary IE */
1267 /* identify if this is Broadcom sta */
1268 /* identify if this is ralink sta */
1269 /* Customer proprietary IE */
1270
1271 /* get a unique AID */
1272 if (pstat->aid == 0) {
1273 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1274 if (!pstapriv->sta_aid[pstat->aid - 1])
1275 break;
1276
1277 /* if (pstat->aid > NUM_STA) { */
1278 if (pstat->aid > pstapriv->max_num_sta) {
1279
1280 pstat->aid = 0;
1281
1282 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1283
1284 goto OnAssocReqFail;
1285
1286
1287 } else {
1288 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1289 }
1290 }
1291
1292
1293 pstat->state &= (~WIFI_FW_ASSOC_STATE);
1294 pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1295
1296 spin_lock_bh(&pstapriv->auth_list_lock);
1297 if (!list_empty(&pstat->auth_list)) {
1298 list_del_init(&pstat->auth_list);
1299 pstapriv->auth_list_cnt--;
1300 }
1301 spin_unlock_bh(&pstapriv->auth_list_lock);
1302
1303 spin_lock_bh(&pstapriv->asoc_list_lock);
1304 if (list_empty(&pstat->asoc_list)) {
1305 pstat->expire_to = pstapriv->expire_to;
1306 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1307 pstapriv->asoc_list_cnt++;
1308 }
1309 spin_unlock_bh(&pstapriv->asoc_list_lock);
1310
1311 /* now the station is qualified to join our BSS... */
1312 if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (status == WLAN_STATUS_SUCCESS)) {
1313 /* 1 bss_cap_update & sta_info_update */
1314 bss_cap_update_on_sta_join(padapter, pstat);
1315 sta_info_update(padapter, pstat);
1316
1317 /* 2 issue assoc rsp before notify station join event. */
1318 if (frame_type == WIFI_ASSOCREQ)
1319 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1320 else
1321 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1322
1323 spin_lock_bh(&pstat->lock);
1324 kfree(pstat->passoc_req);
1325 pstat->assoc_req_len = 0;
1326 pstat->passoc_req = kmemdup(pframe, pkt_len, GFP_ATOMIC);
1327 if (pstat->passoc_req)
1328 pstat->assoc_req_len = pkt_len;
1329
1330 spin_unlock_bh(&pstat->lock);
1331
1332 /* 3-(1) report sta add event */
1333 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1334 }
1335
1336 return _SUCCESS;
1337
1338 asoc_class2_error:
1339
1340 issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1341
1342 return _FAIL;
1343
1344 OnAssocReqFail:
1345
1346 pstat->aid = 0;
1347 if (frame_type == WIFI_ASSOCREQ)
1348 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1349 else
1350 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1351
1352 return _FAIL;
1353 }
1354
OnAssocRsp(struct adapter * padapter,union recv_frame * precv_frame)1355 unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
1356 {
1357 uint i;
1358 int res;
1359 unsigned short status;
1360 struct ndis_80211_var_ie *pIE;
1361 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1362 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1363 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1364 /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
1365 u8 *pframe = precv_frame->u.hdr.rx_data;
1366 uint pkt_len = precv_frame->u.hdr.len;
1367
1368 /* check A1 matches or not */
1369 if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1370 return _SUCCESS;
1371
1372 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1373 return _SUCCESS;
1374
1375 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1376 return _SUCCESS;
1377
1378 timer_delete_sync(&pmlmeext->link_timer);
1379
1380 /* status */
1381 status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
1382 if (status > 0) {
1383 pmlmeinfo->state = WIFI_FW_NULL_STATE;
1384 res = -4;
1385 goto report_assoc_result;
1386 }
1387
1388 /* get capabilities */
1389 pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1390
1391 /* set slot time */
1392 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1393
1394 /* AID */
1395 res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
1396
1397 /* following are moved to join event callback function */
1398 /* to handle HT, WMM, rate adaptive, update MAC reg */
1399 /* for not to handle the synchronous IO in the tasklet */
1400 for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
1401 pIE = (struct ndis_80211_var_ie *)(pframe + i);
1402
1403 switch (pIE->element_id) {
1404 case WLAN_EID_VENDOR_SPECIFIC:
1405 if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
1406 WMM_param_handler(padapter, pIE);
1407 break;
1408
1409 case WLAN_EID_HT_CAPABILITY: /* HT caps */
1410 HT_caps_handler(padapter, pIE);
1411 break;
1412
1413 case WLAN_EID_HT_OPERATION: /* HT info */
1414 HT_info_handler(padapter, pIE);
1415 break;
1416
1417 case WLAN_EID_ERP_INFO:
1418 ERP_IE_handler(padapter, pIE);
1419 break;
1420
1421 default:
1422 break;
1423 }
1424
1425 i += (pIE->length + 2);
1426 }
1427
1428 pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1429 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1430
1431 /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1432 update_basic_rate_table(padapter, pmlmeinfo->network.supported_rates);
1433
1434 report_assoc_result:
1435 if (res > 0)
1436 rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
1437 else
1438 rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
1439
1440 report_join_res(padapter, res);
1441
1442 return _SUCCESS;
1443 }
1444
OnDeAuth(struct adapter * padapter,union recv_frame * precv_frame)1445 unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
1446 {
1447 unsigned short reason;
1448 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1449 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1450 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1451 u8 *pframe = precv_frame->u.hdr.rx_data;
1452 int ignore_received_deauth = 0;
1453
1454 /* check A3 */
1455 if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1456 return _SUCCESS;
1457
1458 reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1459
1460 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1461 struct sta_info *psta;
1462 struct sta_priv *pstapriv = &padapter->stapriv;
1463
1464 /* rtw_free_stainfo(padapter, psta); */
1465
1466 netdev_dbg(padapter->pnetdev,
1467 "ap recv deauth reason code(%d) sta:%pM\n", reason,
1468 GetAddr2Ptr(pframe));
1469
1470 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1471 if (psta) {
1472 u8 updated = false;
1473
1474 spin_lock_bh(&pstapriv->asoc_list_lock);
1475 if (list_empty(&psta->asoc_list) == false) {
1476 list_del_init(&psta->asoc_list);
1477 pstapriv->asoc_list_cnt--;
1478 updated = ap_free_sta(padapter, psta, false, reason);
1479
1480 }
1481 spin_unlock_bh(&pstapriv->asoc_list_lock);
1482
1483 associated_clients_update(padapter, updated);
1484 }
1485
1486
1487 return _SUCCESS;
1488 }
1489
1490 /* Commented by Albert 20130604
1491 * Before sending the auth frame to start the STA/GC mode connection with AP/GO,
1492 * we will send the deauth first.
1493 * However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth.
1494 * Added the following code to avoid this case.
1495 */
1496 if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
1497 (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
1498 if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
1499 ignore_received_deauth = 1;
1500 } else if (reason == WLAN_REASON_PREV_AUTH_NOT_VALID) {
1501 /* TODO: 802.11r */
1502 ignore_received_deauth = 1;
1503 }
1504 }
1505
1506 netdev_dbg(padapter->pnetdev,
1507 "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n",
1508 reason, GetAddr3Ptr(pframe),
1509 ignore_received_deauth);
1510
1511 if (ignore_received_deauth == 0)
1512 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1513
1514 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1515 return _SUCCESS;
1516 }
1517
OnDisassoc(struct adapter * padapter,union recv_frame * precv_frame)1518 unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
1519 {
1520 unsigned short reason;
1521 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1522 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1523 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1524 u8 *pframe = precv_frame->u.hdr.rx_data;
1525
1526 /* check A3 */
1527 if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1528 return _SUCCESS;
1529
1530 reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1531
1532 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1533 struct sta_info *psta;
1534 struct sta_priv *pstapriv = &padapter->stapriv;
1535
1536 /* rtw_free_stainfo(padapter, psta); */
1537
1538 netdev_dbg(padapter->pnetdev,
1539 "ap recv disassoc reason code(%d) sta:%pM\n",
1540 reason, GetAddr2Ptr(pframe));
1541
1542 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1543 if (psta) {
1544 u8 updated = false;
1545
1546 spin_lock_bh(&pstapriv->asoc_list_lock);
1547 if (list_empty(&psta->asoc_list) == false) {
1548 list_del_init(&psta->asoc_list);
1549 pstapriv->asoc_list_cnt--;
1550 updated = ap_free_sta(padapter, psta, false, reason);
1551
1552 }
1553 spin_unlock_bh(&pstapriv->asoc_list_lock);
1554
1555 associated_clients_update(padapter, updated);
1556 }
1557
1558 return _SUCCESS;
1559 }
1560 netdev_dbg(padapter->pnetdev,
1561 "sta recv disassoc reason code(%d) sta:%pM\n",
1562 reason, GetAddr3Ptr(pframe));
1563
1564 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1565
1566 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1567 return _SUCCESS;
1568
1569 }
1570
OnAtim(struct adapter * padapter,union recv_frame * precv_frame)1571 unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
1572 {
1573 return _SUCCESS;
1574 }
1575
on_action_spct(struct adapter * padapter,union recv_frame * precv_frame)1576 unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
1577 {
1578 struct sta_info *psta = NULL;
1579 struct sta_priv *pstapriv = &padapter->stapriv;
1580 u8 *pframe = precv_frame->u.hdr.rx_data;
1581 u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1582 u8 category;
1583 u8 action;
1584
1585 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1586
1587 if (!psta)
1588 goto exit;
1589
1590 category = frame_body[0];
1591 if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
1592 goto exit;
1593
1594 action = frame_body[1];
1595 switch (action) {
1596 case WLAN_ACTION_SPCT_MSR_REQ:
1597 case WLAN_ACTION_SPCT_MSR_RPRT:
1598 case WLAN_ACTION_SPCT_TPC_REQ:
1599 case WLAN_ACTION_SPCT_TPC_RPRT:
1600 case WLAN_ACTION_SPCT_CHL_SWITCH:
1601 break;
1602 default:
1603 break;
1604 }
1605
1606 exit:
1607 return _FAIL;
1608 }
1609
OnAction_back(struct adapter * padapter,union recv_frame * precv_frame)1610 unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
1611 {
1612 u8 *addr;
1613 struct sta_info *psta = NULL;
1614 struct recv_reorder_ctrl *preorder_ctrl;
1615 unsigned char *frame_body;
1616 unsigned char category, action;
1617 unsigned short tid, status;
1618 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1619 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1620 u8 *pframe = precv_frame->u.hdr.rx_data;
1621 struct sta_priv *pstapriv = &padapter->stapriv;
1622
1623 /* check RA matches or not */
1624 if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
1625 return _SUCCESS;
1626
1627 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1628 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1629 return _SUCCESS;
1630
1631 addr = GetAddr2Ptr(pframe);
1632 psta = rtw_get_stainfo(pstapriv, addr);
1633
1634 if (!psta)
1635 return _SUCCESS;
1636
1637 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1638
1639 category = frame_body[0];
1640 if (category == RTW_WLAN_CATEGORY_BACK) {/* representing Block Ack */
1641 if (!pmlmeinfo->HT_enable)
1642 return _SUCCESS;
1643
1644 action = frame_body[1];
1645 switch (action) {
1646 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
1647
1648 memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
1649 /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */
1650 process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
1651
1652 if (pmlmeinfo->accept_addba_req)
1653 issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 0);
1654 else
1655 issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
1656
1657 break;
1658
1659 case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
1660 status = get_unaligned_le16(&frame_body[3]);
1661 tid = ((frame_body[5] >> 2) & 0x7);
1662
1663 if (status == 0) {
1664 /* successful */
1665 psta->htpriv.agg_enable_bitmap |= BIT(tid);
1666 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1667 } else {
1668 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1669 }
1670
1671 if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
1672 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1673 psta->expire_to = pstapriv->expire_to;
1674 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
1675 }
1676
1677 break;
1678
1679 case WLAN_ACTION_DELBA: /* DELBA */
1680 if ((frame_body[3] & BIT(3)) == 0) {
1681 psta->htpriv.agg_enable_bitmap &=
1682 ~BIT((frame_body[3] >> 4) & 0xf);
1683 psta->htpriv.candidate_tid_bitmap &=
1684 ~BIT((frame_body[3] >> 4) & 0xf);
1685 } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
1686 tid = (frame_body[3] >> 4) & 0x0F;
1687
1688 preorder_ctrl = &psta->recvreorder_ctrl[tid];
1689 preorder_ctrl->enable = false;
1690 preorder_ctrl->indicate_seq = 0xffff;
1691 }
1692 /* todo: how to notify the host while receiving DELETE BA */
1693 break;
1694
1695 default:
1696 break;
1697 }
1698 }
1699 return _SUCCESS;
1700 }
1701
rtw_action_public_decache(union recv_frame * recv_frame,s32 token)1702 static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
1703 {
1704 struct adapter *adapter = recv_frame->u.hdr.adapter;
1705 struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
1706 u8 *frame = recv_frame->u.hdr.rx_data;
1707 u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
1708 (recv_frame->u.hdr.attrib.frag_num & 0xf);
1709
1710 if (GetRetry(frame)) {
1711 if (token >= 0) {
1712 if ((seq_ctrl == mlmeext->action_public_rxseq)
1713 && (token == mlmeext->action_public_dialog_token))
1714 return _FAIL;
1715 } else {
1716 if (seq_ctrl == mlmeext->action_public_rxseq)
1717 return _FAIL;
1718 }
1719 }
1720
1721 mlmeext->action_public_rxseq = seq_ctrl;
1722
1723 if (token >= 0)
1724 mlmeext->action_public_dialog_token = token;
1725
1726 return _SUCCESS;
1727 }
1728
on_action_public_p2p(union recv_frame * precv_frame)1729 static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
1730 {
1731 u8 *pframe = precv_frame->u.hdr.rx_data;
1732 u8 *frame_body;
1733 u8 dialogToken = 0;
1734
1735 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1736
1737 dialogToken = frame_body[7];
1738
1739 if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
1740 return _FAIL;
1741
1742 return _SUCCESS;
1743 }
1744
on_action_public_vendor(union recv_frame * precv_frame)1745 static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
1746 {
1747 unsigned int ret = _FAIL;
1748 u8 *pframe = precv_frame->u.hdr.rx_data;
1749 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1750
1751 if (!memcmp(frame_body + 2, P2P_OUI, 4))
1752 ret = on_action_public_p2p(precv_frame);
1753
1754 return ret;
1755 }
1756
on_action_public_default(union recv_frame * precv_frame,u8 action)1757 static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
1758 {
1759 unsigned int ret = _FAIL;
1760 u8 *pframe = precv_frame->u.hdr.rx_data;
1761 uint frame_len = precv_frame->u.hdr.len;
1762 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1763 u8 token;
1764 struct adapter *adapter = precv_frame->u.hdr.adapter;
1765 char msg[64];
1766
1767 token = frame_body[2];
1768
1769 if (rtw_action_public_decache(precv_frame, token) == _FAIL)
1770 goto exit;
1771
1772 scnprintf(msg, sizeof(msg), "%s(token:%u)", action_public_str(action), token);
1773 rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
1774
1775 ret = _SUCCESS;
1776
1777 exit:
1778 return ret;
1779 }
1780
on_action_public(struct adapter * padapter,union recv_frame * precv_frame)1781 unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
1782 {
1783 unsigned int ret = _FAIL;
1784 u8 *pframe = precv_frame->u.hdr.rx_data;
1785 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1786 u8 category, action;
1787
1788 /* check RA matches or not */
1789 if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
1790 goto exit;
1791
1792 category = frame_body[0];
1793 if (category != RTW_WLAN_CATEGORY_PUBLIC)
1794 goto exit;
1795
1796 action = frame_body[1];
1797 switch (action) {
1798 case ACT_PUBLIC_VENDOR:
1799 ret = on_action_public_vendor(precv_frame);
1800 break;
1801 default:
1802 ret = on_action_public_default(precv_frame, action);
1803 break;
1804 }
1805
1806 exit:
1807 return ret;
1808 }
1809
OnAction_ht(struct adapter * padapter,union recv_frame * precv_frame)1810 unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
1811 {
1812 u8 *pframe = precv_frame->u.hdr.rx_data;
1813 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1814 u8 category, action;
1815
1816 /* check RA matches or not */
1817 if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
1818 goto exit;
1819
1820 category = frame_body[0];
1821 if (category != RTW_WLAN_CATEGORY_HT)
1822 goto exit;
1823
1824 action = frame_body[1];
1825 switch (action) {
1826 case WLAN_HT_ACTION_COMPRESSED_BF:
1827 break;
1828 default:
1829 break;
1830 }
1831
1832 exit:
1833
1834 return _SUCCESS;
1835 }
1836
OnAction_sa_query(struct adapter * padapter,union recv_frame * precv_frame)1837 unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame)
1838 {
1839 u8 *pframe = precv_frame->u.hdr.rx_data;
1840 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1841 unsigned short tid;
1842
1843 switch (pframe[WLAN_HDR_A3_LEN+1]) {
1844 case 0: /* SA Query req */
1845 memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short));
1846 issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid);
1847 break;
1848
1849 case 1: /* SA Query rsp */
1850 timer_delete_sync(&pmlmeext->sa_query_timer);
1851 break;
1852 default:
1853 break;
1854 }
1855
1856 return _SUCCESS;
1857 }
1858
OnAction(struct adapter * padapter,union recv_frame * precv_frame)1859 unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
1860 {
1861 int i;
1862 unsigned char category;
1863 struct action_handler *ptable;
1864 unsigned char *frame_body;
1865 u8 *pframe = precv_frame->u.hdr.rx_data;
1866
1867 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1868
1869 category = frame_body[0];
1870
1871 for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) {
1872 ptable = &OnAction_tbl[i];
1873
1874 if (category == ptable->num)
1875 ptable->func(padapter, precv_frame);
1876
1877 }
1878
1879 return _SUCCESS;
1880
1881 }
1882
DoReserved(struct adapter * padapter,union recv_frame * precv_frame)1883 unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
1884 {
1885 return _SUCCESS;
1886 }
1887
_alloc_mgtxmitframe(struct xmit_priv * pxmitpriv,bool once)1888 static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
1889 {
1890 struct xmit_frame *pmgntframe;
1891 struct xmit_buf *pxmitbuf;
1892
1893 if (once)
1894 pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
1895 else
1896 pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
1897
1898 if (!pmgntframe)
1899 goto exit;
1900
1901 pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
1902 if (!pxmitbuf) {
1903 rtw_free_xmitframe(pxmitpriv, pmgntframe);
1904 pmgntframe = NULL;
1905 goto exit;
1906 }
1907
1908 pmgntframe->frame_tag = MGNT_FRAMETAG;
1909 pmgntframe->pxmitbuf = pxmitbuf;
1910 pmgntframe->buf_addr = pxmitbuf->pbuf;
1911 pxmitbuf->priv_data = pmgntframe;
1912
1913 exit:
1914 return pmgntframe;
1915
1916 }
1917
alloc_mgtxmitframe(struct xmit_priv * pxmitpriv)1918 inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
1919 {
1920 return _alloc_mgtxmitframe(pxmitpriv, false);
1921 }
1922
1923 /* Following are some TX functions for WiFi MLME */
1924
update_mgnt_tx_rate(struct adapter * padapter,u8 rate)1925 void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
1926 {
1927 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1928
1929 pmlmeext->tx_rate = rate;
1930 }
1931
update_mgntframe_attrib(struct adapter * padapter,struct pkt_attrib * pattrib)1932 void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
1933 {
1934 u8 wireless_mode;
1935 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1936
1937 /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */
1938
1939 pattrib->hdrlen = 24;
1940 pattrib->nr_frags = 1;
1941 pattrib->priority = 7;
1942 pattrib->mac_id = 0;
1943 pattrib->qsel = 0x12;
1944
1945 pattrib->pktlen = 0;
1946
1947 if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
1948 wireless_mode = WIRELESS_11B;
1949 else
1950 wireless_mode = WIRELESS_11G;
1951 pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode);
1952 pattrib->rate = pmlmeext->tx_rate;
1953
1954 pattrib->encrypt = _NO_PRIVACY_;
1955 pattrib->bswenc = false;
1956
1957 pattrib->qos_en = false;
1958 pattrib->ht_en = false;
1959 pattrib->bwmode = CHANNEL_WIDTH_20;
1960 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1961 pattrib->sgi = false;
1962
1963 pattrib->seqnum = pmlmeext->mgnt_seq;
1964
1965 pattrib->retry_ctrl = true;
1966
1967 pattrib->mbssid = 0;
1968
1969 }
1970
update_mgntframe_attrib_addr(struct adapter * padapter,struct xmit_frame * pmgntframe)1971 void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe)
1972 {
1973 u8 *pframe;
1974 struct pkt_attrib *pattrib = &pmgntframe->attrib;
1975
1976 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1977
1978 memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
1979 memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
1980 }
1981
dump_mgntframe(struct adapter * padapter,struct xmit_frame * pmgntframe)1982 void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
1983 {
1984 if (padapter->bSurpriseRemoved ||
1985 padapter->bDriverStopped) {
1986 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
1987 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
1988 return;
1989 }
1990
1991 rtw_hal_mgnt_xmit(padapter, pmgntframe);
1992 }
1993
dump_mgntframe_and_wait(struct adapter * padapter,struct xmit_frame * pmgntframe,int timeout_ms)1994 s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
1995 {
1996 s32 ret = _FAIL;
1997 unsigned long irqL;
1998 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1999 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2000 struct submit_ctx sctx;
2001
2002 if (padapter->bSurpriseRemoved ||
2003 padapter->bDriverStopped) {
2004 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2005 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2006 return ret;
2007 }
2008
2009 rtw_sctx_init(&sctx, timeout_ms);
2010 pxmitbuf->sctx = &sctx;
2011
2012 ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
2013
2014 if (ret == _SUCCESS)
2015 ret = rtw_sctx_wait(&sctx);
2016
2017 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2018 pxmitbuf->sctx = NULL;
2019 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2020
2021 return ret;
2022 }
2023
dump_mgntframe_and_wait_ack(struct adapter * padapter,struct xmit_frame * pmgntframe)2024 s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
2025 {
2026 static u8 seq_no;
2027 s32 ret = _FAIL;
2028 u32 timeout_ms = 500;/* 500ms */
2029 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2030
2031 if (padapter->bSurpriseRemoved ||
2032 padapter->bDriverStopped) {
2033 rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2034 rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2035 return -1;
2036 }
2037
2038 if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) {
2039 pxmitpriv->ack_tx = true;
2040 pxmitpriv->seq_no = seq_no++;
2041 pmgntframe->ack_report = 1;
2042 if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2043 ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
2044
2045 pxmitpriv->ack_tx = false;
2046 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2047 }
2048
2049 return ret;
2050 }
2051
update_hidden_ssid(u8 * ies,u32 ies_len,u8 hidden_ssid_mode)2052 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2053 {
2054 u8 *ssid_ie;
2055 signed int ssid_len_ori;
2056 int len_diff = 0;
2057
2058 ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
2059
2060 if (ssid_ie && ssid_len_ori > 0) {
2061 switch (hidden_ssid_mode) {
2062 case 1:
2063 {
2064 u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
2065 u32 remain_len = 0;
2066
2067 remain_len = ies_len - (next_ie-ies);
2068
2069 ssid_ie[1] = 0;
2070 memcpy(ssid_ie+2, next_ie, remain_len);
2071 len_diff -= ssid_len_ori;
2072
2073 break;
2074 }
2075 case 2:
2076 memset(&ssid_ie[2], 0, ssid_len_ori);
2077 break;
2078 default:
2079 break;
2080 }
2081 }
2082
2083 return len_diff;
2084 }
2085
issue_beacon(struct adapter * padapter,int timeout_ms)2086 void issue_beacon(struct adapter *padapter, int timeout_ms)
2087 {
2088 struct xmit_frame *pmgntframe;
2089 struct pkt_attrib *pattrib;
2090 unsigned char *pframe;
2091 struct ieee80211_hdr *pwlanhdr;
2092 __le16 *fctrl;
2093 unsigned int rate_len;
2094 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2095 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2096 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2097 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2098 struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
2099
2100 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2101 if (!pmgntframe)
2102 return;
2103
2104 spin_lock_bh(&pmlmepriv->bcn_update_lock);
2105
2106 /* update attribute */
2107 pattrib = &pmgntframe->attrib;
2108 update_mgntframe_attrib(padapter, pattrib);
2109 pattrib->qsel = 0x10;
2110
2111 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2112
2113 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2114 pwlanhdr = (struct ieee80211_hdr *)pframe;
2115
2116
2117 fctrl = &(pwlanhdr->frame_control);
2118 *(fctrl) = 0;
2119
2120 eth_broadcast_addr(pwlanhdr->addr1);
2121 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2122 memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
2123
2124 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
2125 /* pmlmeext->mgnt_seq++; */
2126 SetFrameSubType(pframe, WIFI_BEACON);
2127
2128 pframe += sizeof(struct ieee80211_hdr_3addr);
2129 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2130
2131 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2132 {
2133 int len_diff;
2134
2135 memcpy(pframe, cur_network->ies, cur_network->ie_length);
2136 len_diff = update_hidden_ssid(pframe+_BEACON_IE_OFFSET_,
2137 cur_network->ie_length-_BEACON_IE_OFFSET_,
2138 pmlmeinfo->hidden_ssid_mode);
2139 pframe += (cur_network->ie_length+len_diff);
2140 pattrib->pktlen += (cur_network->ie_length+len_diff);
2141 }
2142
2143 {
2144 u8 *wps_ie;
2145 uint wps_ielen;
2146 u8 sr = 0;
2147
2148 wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
2149 pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
2150 if (wps_ie && wps_ielen > 0)
2151 rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
2152 if (sr != 0)
2153 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2154 else
2155 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2156 }
2157
2158 goto _issue_bcn;
2159
2160 }
2161
2162 /* below for ad-hoc mode */
2163
2164 /* timestamp will be inserted by hardware */
2165 pframe += 8;
2166 pattrib->pktlen += 8;
2167
2168 /* beacon interval: 2 bytes */
2169
2170 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
2171
2172 pframe += 2;
2173 pattrib->pktlen += 2;
2174
2175 /* capability info: 2 bytes */
2176
2177 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
2178
2179 pframe += 2;
2180 pattrib->pktlen += 2;
2181
2182 /* SSID */
2183 pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
2184
2185 /* supported rates... */
2186 rate_len = rtw_get_rateset_len(cur_network->supported_rates);
2187 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pattrib->pktlen);
2188
2189 /* DS parameter set */
2190 pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &pattrib->pktlen);
2191
2192 /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
2193 {
2194 u8 erpinfo = 0;
2195 u32 ATIMWindow;
2196 /* IBSS Parameter Set... */
2197 /* ATIMWindow = cur->configuration.ATIMWindow; */
2198 ATIMWindow = 0;
2199 pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2200
2201 /* ERP IE */
2202 pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen);
2203 }
2204
2205
2206 /* EXTERNDED SUPPORTED RATE */
2207 if (rate_len > 8)
2208 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->supported_rates + 8), &pattrib->pktlen);
2209
2210
2211 /* todo:HT for adhoc */
2212
2213 _issue_bcn:
2214
2215 pmlmepriv->update_bcn = false;
2216
2217 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2218
2219 if ((pattrib->pktlen + TXDESC_SIZE) > 512)
2220 return;
2221
2222 pattrib->last_txcmdsz = pattrib->pktlen;
2223
2224 if (timeout_ms > 0)
2225 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
2226 else
2227 dump_mgntframe(padapter, pmgntframe);
2228
2229 }
2230
issue_probersp(struct adapter * padapter,unsigned char * da,u8 is_valid_p2p_probereq)2231 void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
2232 {
2233 struct xmit_frame *pmgntframe;
2234 struct pkt_attrib *pattrib;
2235 unsigned char *pframe;
2236 struct ieee80211_hdr *pwlanhdr;
2237 __le16 *fctrl;
2238 unsigned char *mac, *bssid;
2239 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2240
2241 u8 *pwps_ie;
2242 uint wps_ielen;
2243 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2244 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2245 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2246 struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
2247 unsigned int rate_len;
2248
2249 if (!da)
2250 return;
2251
2252 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2253 if (!pmgntframe)
2254 return;
2255
2256 /* update attribute */
2257 pattrib = &pmgntframe->attrib;
2258 update_mgntframe_attrib(padapter, pattrib);
2259
2260 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2261
2262 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2263 pwlanhdr = (struct ieee80211_hdr *)pframe;
2264
2265 mac = myid(&(padapter->eeprompriv));
2266 bssid = cur_network->mac_address;
2267
2268 fctrl = &(pwlanhdr->frame_control);
2269 *(fctrl) = 0;
2270 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2271 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2272 memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
2273
2274 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2275 pmlmeext->mgnt_seq++;
2276 SetFrameSubType(fctrl, WIFI_PROBERSP);
2277
2278 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2279 pattrib->pktlen = pattrib->hdrlen;
2280 pframe += pattrib->hdrlen;
2281
2282
2283 if (cur_network->ie_length > MAX_IE_SZ)
2284 return;
2285
2286 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2287 pwps_ie = rtw_get_wps_ie(cur_network->ies+_FIXED_IE_LENGTH_, cur_network->ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
2288
2289 /* inerset & update wps_probe_resp_ie */
2290 if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
2291 uint wps_offset, remainder_ielen;
2292 u8 *premainder_ie;
2293
2294 wps_offset = (uint)(pwps_ie - cur_network->ies);
2295
2296 premainder_ie = pwps_ie + wps_ielen;
2297
2298 remainder_ielen = cur_network->ie_length - wps_offset - wps_ielen;
2299
2300 memcpy(pframe, cur_network->ies, wps_offset);
2301 pframe += wps_offset;
2302 pattrib->pktlen += wps_offset;
2303
2304 wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
2305 if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
2306 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
2307 pframe += wps_ielen+2;
2308 pattrib->pktlen += wps_ielen+2;
2309 }
2310
2311 if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
2312 memcpy(pframe, premainder_ie, remainder_ielen);
2313 pframe += remainder_ielen;
2314 pattrib->pktlen += remainder_ielen;
2315 }
2316 } else {
2317 memcpy(pframe, cur_network->ies, cur_network->ie_length);
2318 pframe += cur_network->ie_length;
2319 pattrib->pktlen += cur_network->ie_length;
2320 }
2321
2322 /* retrieve SSID IE from cur_network->ssid */
2323 {
2324 u8 *ssid_ie;
2325 signed int ssid_ielen;
2326 signed int ssid_ielen_diff;
2327 u8 *buf;
2328 u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr);
2329
2330 buf = kzalloc(MAX_IE_SZ, GFP_ATOMIC);
2331 if (!buf)
2332 return;
2333
2334 ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, WLAN_EID_SSID, &ssid_ielen,
2335 (pframe-ies)-_FIXED_IE_LENGTH_);
2336
2337 ssid_ielen_diff = cur_network->ssid.ssid_length - ssid_ielen;
2338
2339 if (ssid_ie && cur_network->ssid.ssid_length) {
2340 uint remainder_ielen;
2341 u8 *remainder_ie;
2342
2343 remainder_ie = ssid_ie+2;
2344 remainder_ielen = (pframe-remainder_ie);
2345
2346 if (remainder_ielen > MAX_IE_SZ) {
2347 netdev_warn(padapter->pnetdev,
2348 FUNC_ADPT_FMT " remainder_ielen > MAX_IE_SZ\n",
2349 FUNC_ADPT_ARG(padapter));
2350 remainder_ielen = MAX_IE_SZ;
2351 }
2352
2353 memcpy(buf, remainder_ie, remainder_ielen);
2354 memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
2355 *(ssid_ie+1) = cur_network->ssid.ssid_length;
2356 memcpy(ssid_ie+2, cur_network->ssid.ssid, cur_network->ssid.ssid_length);
2357
2358 pframe += ssid_ielen_diff;
2359 pattrib->pktlen += ssid_ielen_diff;
2360 }
2361 kfree(buf);
2362 }
2363 } else {
2364 /* timestamp will be inserted by hardware */
2365 pframe += 8;
2366 pattrib->pktlen += 8;
2367
2368 /* beacon interval: 2 bytes */
2369
2370 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
2371
2372 pframe += 2;
2373 pattrib->pktlen += 2;
2374
2375 /* capability info: 2 bytes */
2376
2377 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
2378
2379 pframe += 2;
2380 pattrib->pktlen += 2;
2381
2382 /* below for ad-hoc mode */
2383
2384 /* SSID */
2385 pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
2386
2387 /* supported rates... */
2388 rate_len = rtw_get_rateset_len(cur_network->supported_rates);
2389 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pattrib->pktlen);
2390
2391 /* DS parameter set */
2392 pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &pattrib->pktlen);
2393
2394 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
2395 u8 erpinfo = 0;
2396 u32 ATIMWindow;
2397 /* IBSS Parameter Set... */
2398 /* ATIMWindow = cur->configuration.ATIMWindow; */
2399 ATIMWindow = 0;
2400 pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2401
2402 /* ERP IE */
2403 pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen);
2404 }
2405
2406
2407 /* EXTERNDED SUPPORTED RATE */
2408 if (rate_len > 8)
2409 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->supported_rates + 8), &pattrib->pktlen);
2410
2411
2412 /* todo:HT for adhoc */
2413
2414 }
2415
2416 pattrib->last_txcmdsz = pattrib->pktlen;
2417
2418
2419 dump_mgntframe(padapter, pmgntframe);
2420
2421 return;
2422
2423 }
2424
_issue_probereq(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da,u8 ch,bool append_wps,bool wait_ack)2425 static int _issue_probereq(struct adapter *padapter,
2426 struct ndis_802_11_ssid *pssid,
2427 u8 *da, u8 ch, bool append_wps, bool wait_ack)
2428 {
2429 int ret = _FAIL;
2430 struct xmit_frame *pmgntframe;
2431 struct pkt_attrib *pattrib;
2432 unsigned char *pframe;
2433 struct ieee80211_hdr *pwlanhdr;
2434 __le16 *fctrl;
2435 unsigned char *mac;
2436 unsigned char bssrate[NumRates];
2437 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2438 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2439 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2440 int bssrate_len = 0;
2441
2442 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2443 if (!pmgntframe)
2444 goto exit;
2445
2446 /* update attribute */
2447 pattrib = &pmgntframe->attrib;
2448 update_mgntframe_attrib(padapter, pattrib);
2449
2450
2451 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2452
2453 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2454 pwlanhdr = (struct ieee80211_hdr *)pframe;
2455
2456 mac = myid(&(padapter->eeprompriv));
2457
2458 fctrl = &(pwlanhdr->frame_control);
2459 *(fctrl) = 0;
2460
2461 if (da) {
2462 /* unicast probe request frame */
2463 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2464 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
2465 } else {
2466 /* broadcast probe request frame */
2467 eth_broadcast_addr(pwlanhdr->addr1);
2468 eth_broadcast_addr(pwlanhdr->addr3);
2469 }
2470
2471 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2472
2473 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2474 pmlmeext->mgnt_seq++;
2475 SetFrameSubType(pframe, WIFI_PROBEREQ);
2476
2477 pframe += sizeof(struct ieee80211_hdr_3addr);
2478 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2479
2480 if (pssid)
2481 pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->ssid_length, pssid->ssid, &(pattrib->pktlen));
2482 else
2483 pframe = rtw_set_ie(pframe, WLAN_EID_SSID, 0, NULL, &(pattrib->pktlen));
2484
2485 get_rate_set(padapter, bssrate, &bssrate_len);
2486
2487 if (bssrate_len > 8) {
2488 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen));
2489 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
2490 } else {
2491 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen));
2492 }
2493
2494 if (ch)
2495 pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, &ch, &pattrib->pktlen);
2496
2497 if (append_wps) {
2498 /* add wps_ie for wps2.0 */
2499 if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
2500 memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
2501 pframe += pmlmepriv->wps_probe_req_ie_len;
2502 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2503 }
2504 }
2505
2506 pattrib->last_txcmdsz = pattrib->pktlen;
2507
2508 if (wait_ack) {
2509 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
2510 } else {
2511 dump_mgntframe(padapter, pmgntframe);
2512 ret = _SUCCESS;
2513 }
2514
2515 exit:
2516 return ret;
2517 }
2518
issue_probereq(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da)2519 inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
2520 {
2521 _issue_probereq(padapter, pssid, da, 0, 1, false);
2522 }
2523
issue_probereq_ex(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da,u8 ch,bool append_wps,int try_cnt,int wait_ms)2524 int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps,
2525 int try_cnt, int wait_ms)
2526 {
2527 int ret;
2528 int i = 0;
2529
2530 do {
2531 ret = _issue_probereq(padapter, pssid, da, ch, append_wps,
2532 wait_ms > 0);
2533
2534 i++;
2535
2536 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2537 break;
2538
2539 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2540 msleep(wait_ms);
2541
2542 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2543
2544 if (ret != _FAIL) {
2545 ret = _SUCCESS;
2546 #ifndef DBG_XMIT_ACK
2547 goto exit;
2548 #endif
2549 }
2550
2551 exit:
2552 return ret;
2553 }
2554
2555 /* if psta == NULL, indicate we are station(client) now... */
issue_auth(struct adapter * padapter,struct sta_info * psta,unsigned short status)2556 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
2557 {
2558 struct xmit_frame *pmgntframe;
2559 struct pkt_attrib *pattrib;
2560 unsigned char *pframe;
2561 struct ieee80211_hdr *pwlanhdr;
2562 __le16 *fctrl;
2563 unsigned int val32;
2564 unsigned short val16;
2565 int use_shared_key = 0;
2566 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2567 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2568 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2569 __le16 le_tmp;
2570
2571 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2572 if (!pmgntframe)
2573 return;
2574
2575 /* update attribute */
2576 pattrib = &pmgntframe->attrib;
2577 update_mgntframe_attrib(padapter, pattrib);
2578
2579 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2580
2581 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2582 pwlanhdr = (struct ieee80211_hdr *)pframe;
2583
2584 fctrl = &(pwlanhdr->frame_control);
2585 *(fctrl) = 0;
2586
2587 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2588 pmlmeext->mgnt_seq++;
2589 SetFrameSubType(pframe, WIFI_AUTH);
2590
2591 pframe += sizeof(struct ieee80211_hdr_3addr);
2592 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2593
2594
2595 if (psta) { /* for AP mode */
2596 memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
2597 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2598 memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2599
2600 /* setting auth algo number */
2601 val16 = (u16)psta->authalg;
2602
2603 if (status != WLAN_STATUS_SUCCESS)
2604 val16 = 0;
2605
2606 if (val16)
2607 use_shared_key = 1;
2608
2609 le_tmp = cpu_to_le16(val16);
2610
2611 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2612
2613 /* setting auth seq number */
2614 val16 = (u16)psta->auth_seq;
2615 le_tmp = cpu_to_le16(val16);
2616 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2617
2618 /* setting status code... */
2619 val16 = status;
2620 le_tmp = cpu_to_le16(val16);
2621 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2622
2623 /* added challenging text... */
2624 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
2625 pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, psta->chg_txt, &(pattrib->pktlen));
2626
2627 } else {
2628 memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
2629 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2630 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
2631
2632 /* setting auth algo number */
2633 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */
2634 if (val16)
2635 use_shared_key = 1;
2636 le_tmp = cpu_to_le16(val16);
2637
2638 /* setting IV for auth seq #3 */
2639 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
2640 __le32 le_tmp32;
2641
2642 val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
2643 le_tmp32 = cpu_to_le32(val32);
2644 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
2645
2646 pattrib->iv_len = 4;
2647 }
2648
2649 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2650
2651 /* setting auth seq number */
2652 le_tmp = cpu_to_le16(pmlmeinfo->auth_seq);
2653 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2654
2655
2656 /* setting status code... */
2657 le_tmp = cpu_to_le16(status);
2658 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2659
2660 /* then checking to see if sending challenging text... */
2661 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
2662 pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
2663
2664 SetPrivacy(fctrl);
2665
2666 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2667
2668 pattrib->encrypt = _WEP40_;
2669
2670 pattrib->icv_len = 4;
2671
2672 pattrib->pktlen += pattrib->icv_len;
2673
2674 }
2675
2676 }
2677
2678 pattrib->last_txcmdsz = pattrib->pktlen;
2679
2680 rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
2681 dump_mgntframe(padapter, pmgntframe);
2682 }
2683
2684
issue_asocrsp(struct adapter * padapter,unsigned short status,struct sta_info * pstat,int pkt_type)2685 void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
2686 {
2687 struct xmit_frame *pmgntframe;
2688 struct ieee80211_hdr *pwlanhdr;
2689 struct pkt_attrib *pattrib;
2690 unsigned char *pbuf, *pframe;
2691 unsigned short val;
2692 __le16 *fctrl;
2693 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2694 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2695 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2696 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2697 struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
2698 u8 *ie = pnetwork->ies;
2699 __le16 lestatus, le_tmp;
2700
2701 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2702 if (!pmgntframe)
2703 return;
2704
2705 /* update attribute */
2706 pattrib = &pmgntframe->attrib;
2707 update_mgntframe_attrib(padapter, pattrib);
2708
2709
2710 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2711
2712 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2713 pwlanhdr = (struct ieee80211_hdr *)pframe;
2714
2715 fctrl = &(pwlanhdr->frame_control);
2716 *(fctrl) = 0;
2717
2718 memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
2719 memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
2720 memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2721
2722
2723 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2724 pmlmeext->mgnt_seq++;
2725 if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
2726 SetFrameSubType(pwlanhdr, pkt_type);
2727 else
2728 return;
2729
2730 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2731 pattrib->pktlen += pattrib->hdrlen;
2732 pframe += pattrib->hdrlen;
2733
2734 /* capability */
2735 val = *(unsigned short *)rtw_get_capability_from_ie(ie);
2736
2737 pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen));
2738
2739 lestatus = cpu_to_le16(status);
2740 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen));
2741
2742 le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
2743 pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2744
2745 if (pstat->bssratelen <= 8) {
2746 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
2747 } else {
2748 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, pstat->bssrateset, &(pattrib->pktlen));
2749 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
2750 }
2751
2752 if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
2753 uint ie_len = 0;
2754
2755 /* FILL HT CAP INFO IE */
2756 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
2757 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
2758 if (pbuf && ie_len > 0) {
2759 memcpy(pframe, pbuf, ie_len+2);
2760 pframe += (ie_len+2);
2761 pattrib->pktlen += (ie_len+2);
2762 }
2763
2764 /* FILL HT ADD INFO IE */
2765 /* p = hostapd_eid_ht_operation(hapd, p); */
2766 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
2767 if (pbuf && ie_len > 0) {
2768 memcpy(pframe, pbuf, ie_len+2);
2769 pframe += (ie_len+2);
2770 pattrib->pktlen += (ie_len+2);
2771 }
2772
2773 }
2774
2775 /* FILL WMM IE */
2776 if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
2777 uint ie_len = 0;
2778 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
2779
2780 for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
2781 pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
2782 if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
2783 memcpy(pframe, pbuf, ie_len+2);
2784 pframe += (ie_len+2);
2785 pattrib->pktlen += (ie_len+2);
2786
2787 break;
2788 }
2789
2790 if (!pbuf || ie_len == 0)
2791 break;
2792 }
2793
2794 }
2795
2796 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
2797 pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen));
2798
2799 /* add WPS IE ie for wps 2.0 */
2800 if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
2801 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
2802
2803 pframe += pmlmepriv->wps_assoc_resp_ie_len;
2804 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
2805 }
2806
2807 pattrib->last_txcmdsz = pattrib->pktlen;
2808
2809 dump_mgntframe(padapter, pmgntframe);
2810 }
2811
issue_assocreq(struct adapter * padapter)2812 void issue_assocreq(struct adapter *padapter)
2813 {
2814 int ret = _FAIL;
2815 struct xmit_frame *pmgntframe;
2816 struct pkt_attrib *pattrib;
2817 unsigned char *pframe;
2818 struct ieee80211_hdr *pwlanhdr;
2819 __le16 *fctrl;
2820 __le16 val16;
2821 unsigned int i, j, index = 0;
2822 unsigned char bssrate[NumRates], sta_bssrate[NumRates];
2823 struct ndis_80211_var_ie *pIE;
2824 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2825 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2826 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2827 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2828 int bssrate_len = 0, sta_bssrate_len = 0;
2829 u8 vs_ie_length = 0;
2830
2831 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2832 if (!pmgntframe)
2833 goto exit;
2834
2835 /* update attribute */
2836 pattrib = &pmgntframe->attrib;
2837 update_mgntframe_attrib(padapter, pattrib);
2838
2839 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2840
2841 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2842 pwlanhdr = (struct ieee80211_hdr *)pframe;
2843
2844 fctrl = &(pwlanhdr->frame_control);
2845 *(fctrl) = 0;
2846 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2847 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2848 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2849
2850 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2851 pmlmeext->mgnt_seq++;
2852 SetFrameSubType(pframe, WIFI_ASSOCREQ);
2853
2854 pframe += sizeof(struct ieee80211_hdr_3addr);
2855 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2856
2857 /* caps */
2858 memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.ies), 2);
2859
2860 pframe += 2;
2861 pattrib->pktlen += 2;
2862
2863 /* listen interval */
2864 /* todo: listen interval for power saving */
2865 val16 = cpu_to_le16(3);
2866 memcpy(pframe, (unsigned char *)&val16, 2);
2867 pframe += 2;
2868 pattrib->pktlen += 2;
2869
2870 /* SSID */
2871 pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pmlmeinfo->network.ssid.ssid_length, pmlmeinfo->network.ssid.ssid, &(pattrib->pktlen));
2872
2873 /* supported rate & extended supported rate */
2874
2875 /* Check if the AP's supported rates are also supported by STA. */
2876 get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
2877
2878 if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */
2879 sta_bssrate_len = 4;
2880
2881
2882 /* for (i = 0; i < sta_bssrate_len; i++) { */
2883 /* */
2884
2885 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
2886 if (pmlmeinfo->network.supported_rates[i] == 0)
2887 break;
2888 }
2889
2890
2891 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
2892 if (pmlmeinfo->network.supported_rates[i] == 0)
2893 break;
2894
2895
2896 /* Check if the AP's supported rates are also supported by STA. */
2897 for (j = 0; j < sta_bssrate_len; j++) {
2898 /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
2899 if ((pmlmeinfo->network.supported_rates[i] | IEEE80211_BASIC_RATE_MASK)
2900 == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
2901 break;
2902 }
2903
2904 if (j != sta_bssrate_len)
2905 /* the rate is supported by STA */
2906 bssrate[index++] = pmlmeinfo->network.supported_rates[i];
2907 }
2908
2909 bssrate_len = index;
2910
2911 if (bssrate_len == 0) {
2912 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
2913 rtw_free_xmitframe(pxmitpriv, pmgntframe);
2914 goto exit; /* don't connect to AP if no joint supported rate */
2915 }
2916
2917
2918 if (bssrate_len > 8) {
2919 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen));
2920 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
2921 } else
2922 pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen));
2923
2924 /* vendor specific IE, such as WPA, WMM, WPS */
2925 for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.ie_length;) {
2926 pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i);
2927
2928 switch (pIE->element_id) {
2929 case WLAN_EID_VENDOR_SPECIFIC:
2930 if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
2931 (!memcmp(pIE->data, WMM_OUI, 4)) ||
2932 (!memcmp(pIE->data, WPS_OUI, 4))) {
2933 vs_ie_length = pIE->length;
2934 if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) {
2935 /* Commented by Kurt 20110629
2936 * In some older APs, WPS handshake
2937 * would be fail if we append vendor
2938 * extensions information to AP
2939 */
2940
2941 vs_ie_length = 14;
2942 }
2943
2944 pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, vs_ie_length, pIE->data, &(pattrib->pktlen));
2945 }
2946 break;
2947
2948 case WLAN_EID_RSN:
2949 pframe = rtw_set_ie(pframe, WLAN_EID_RSN, pIE->length, pIE->data, &(pattrib->pktlen));
2950 break;
2951 case WLAN_EID_HT_CAPABILITY:
2952 if (padapter->mlmepriv.htpriv.ht_option) {
2953 if (!(is_ap_in_tkip(padapter))) {
2954 memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
2955 pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, pIE->length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
2956 }
2957 }
2958 break;
2959
2960 case WLAN_EID_EXT_CAPABILITY:
2961 if (padapter->mlmepriv.htpriv.ht_option)
2962 pframe = rtw_set_ie(pframe, WLAN_EID_EXT_CAPABILITY, pIE->length, pIE->data, &(pattrib->pktlen));
2963 break;
2964 default:
2965 break;
2966 }
2967
2968 i += (pIE->length + 2);
2969 }
2970
2971 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
2972 pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen));
2973
2974
2975 pattrib->last_txcmdsz = pattrib->pktlen;
2976 dump_mgntframe(padapter, pmgntframe);
2977
2978 ret = _SUCCESS;
2979
2980 exit:
2981 if (ret == _SUCCESS)
2982 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
2983 else
2984 rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
2985 }
2986
2987 /* when wait_ack is true, this function should be called at process context */
_issue_nulldata(struct adapter * padapter,unsigned char * da,unsigned int power_mode,bool wait_ack)2988 static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
2989 unsigned int power_mode, bool wait_ack)
2990 {
2991 int ret = _FAIL;
2992 struct xmit_frame *pmgntframe;
2993 struct pkt_attrib *pattrib;
2994 unsigned char *pframe;
2995 struct ieee80211_hdr *pwlanhdr;
2996 __le16 *fctrl;
2997 struct xmit_priv *pxmitpriv;
2998 struct mlme_ext_priv *pmlmeext;
2999 struct mlme_ext_info *pmlmeinfo;
3000
3001 if (!padapter)
3002 goto exit;
3003
3004 pxmitpriv = &(padapter->xmitpriv);
3005 pmlmeext = &(padapter->mlmeextpriv);
3006 pmlmeinfo = &pmlmeext->mlmext_info;
3007
3008 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3009 if (!pmgntframe)
3010 goto exit;
3011
3012 /* update attribute */
3013 pattrib = &pmgntframe->attrib;
3014 update_mgntframe_attrib(padapter, pattrib);
3015 pattrib->retry_ctrl = false;
3016
3017 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3018
3019 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3020 pwlanhdr = (struct ieee80211_hdr *)pframe;
3021
3022 fctrl = &(pwlanhdr->frame_control);
3023 *(fctrl) = 0;
3024
3025 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3026 SetFrDs(fctrl);
3027 else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3028 SetToDs(fctrl);
3029
3030 if (power_mode)
3031 SetPwrMgt(fctrl);
3032
3033 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3034 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3035 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3036
3037 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3038 pmlmeext->mgnt_seq++;
3039 SetFrameSubType(pframe, WIFI_DATA_NULL);
3040
3041 pframe += sizeof(struct ieee80211_hdr_3addr);
3042 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3043
3044 pattrib->last_txcmdsz = pattrib->pktlen;
3045
3046 if (wait_ack) {
3047 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3048 } else {
3049 dump_mgntframe(padapter, pmgntframe);
3050 ret = _SUCCESS;
3051 }
3052
3053 exit:
3054 return ret;
3055 }
3056
3057 /*
3058 * [IMPORTANT] Don't call this function in interrupt context
3059 *
3060 * When wait_ms > 0, this function should be called at process context
3061 * da == NULL for station mode
3062 */
issue_nulldata(struct adapter * padapter,unsigned char * da,unsigned int power_mode,int try_cnt,int wait_ms)3063 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
3064 {
3065 int ret;
3066 int i = 0;
3067 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3068 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3069 struct sta_info *psta;
3070
3071
3072 /* da == NULL, assume it's null data for sta to ap*/
3073 if (!da)
3074 da = get_my_bssid(&(pmlmeinfo->network));
3075
3076 psta = rtw_get_stainfo(&padapter->stapriv, da);
3077 if (psta) {
3078 if (power_mode)
3079 rtw_hal_macid_sleep(padapter, psta->mac_id);
3080 else
3081 rtw_hal_macid_wakeup(padapter, psta->mac_id);
3082 } else {
3083 rtw_warn_on(1);
3084 }
3085
3086 do {
3087 ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
3088
3089 i++;
3090
3091 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3092 break;
3093
3094 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3095 msleep(wait_ms);
3096
3097 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3098
3099 if (ret != _FAIL) {
3100 ret = _SUCCESS;
3101 #ifndef DBG_XMIT_ACK
3102 goto exit;
3103 #endif
3104 }
3105
3106 exit:
3107 return ret;
3108 }
3109
3110 /*
3111 * [IMPORTANT] This function run in interrupt context
3112 *
3113 * The null data packet would be sent without power bit,
3114 * and not guarantee success.
3115 */
issue_nulldata_in_interrupt(struct adapter * padapter,u8 * da)3116 s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da)
3117 {
3118 struct mlme_ext_priv *pmlmeext;
3119 struct mlme_ext_info *pmlmeinfo;
3120
3121
3122 pmlmeext = &padapter->mlmeextpriv;
3123 pmlmeinfo = &pmlmeext->mlmext_info;
3124
3125 /* da == NULL, assume it's null data for sta to ap*/
3126 if (!da)
3127 da = get_my_bssid(&(pmlmeinfo->network));
3128
3129 return _issue_nulldata(padapter, da, 0, false);
3130 }
3131
3132 /* when wait_ack is true, this function should be called at process context */
_issue_qos_nulldata(struct adapter * padapter,unsigned char * da,u16 tid,bool wait_ack)3133 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
3134 u16 tid, bool wait_ack)
3135 {
3136 int ret = _FAIL;
3137 struct xmit_frame *pmgntframe;
3138 struct pkt_attrib *pattrib;
3139 unsigned char *pframe;
3140 struct ieee80211_hdr *pwlanhdr;
3141 __le16 *fctrl;
3142 u16 *qc;
3143 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
3144 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3145 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3146
3147 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3148 if (!pmgntframe)
3149 goto exit;
3150
3151 /* update attribute */
3152 pattrib = &pmgntframe->attrib;
3153 update_mgntframe_attrib(padapter, pattrib);
3154
3155 pattrib->hdrlen += 2;
3156 pattrib->qos_en = true;
3157 pattrib->eosp = 1;
3158 pattrib->ack_policy = 0;
3159 pattrib->mdata = 0;
3160
3161 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3162
3163 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3164 pwlanhdr = (struct ieee80211_hdr *)pframe;
3165
3166 fctrl = &(pwlanhdr->frame_control);
3167 *(fctrl) = 0;
3168
3169 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3170 SetFrDs(fctrl);
3171 else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3172 SetToDs(fctrl);
3173
3174 qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
3175
3176 SetPriority(qc, tid);
3177
3178 SetEOSP(qc, pattrib->eosp);
3179
3180 SetAckpolicy(qc, pattrib->ack_policy);
3181
3182 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3183 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3184 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3185
3186 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3187 pmlmeext->mgnt_seq++;
3188 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
3189
3190 pframe += sizeof(struct ieee80211_qos_hdr);
3191 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3192
3193 pattrib->last_txcmdsz = pattrib->pktlen;
3194
3195 if (wait_ack) {
3196 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3197 } else {
3198 dump_mgntframe(padapter, pmgntframe);
3199 ret = _SUCCESS;
3200 }
3201
3202 exit:
3203 return ret;
3204 }
3205
3206 /* when wait_ms >0 , this function should be called at process context */
3207 /* da == NULL for station mode */
issue_qos_nulldata(struct adapter * padapter,unsigned char * da,u16 tid,int try_cnt,int wait_ms)3208 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
3209 {
3210 int ret;
3211 int i = 0;
3212 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3213 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3214
3215 /* da == NULL, assume it's null data for sta to ap*/
3216 if (!da)
3217 da = get_my_bssid(&(pmlmeinfo->network));
3218
3219 do {
3220 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
3221
3222 i++;
3223
3224 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3225 break;
3226
3227 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3228 msleep(wait_ms);
3229
3230 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3231
3232 if (ret != _FAIL) {
3233 ret = _SUCCESS;
3234 #ifndef DBG_XMIT_ACK
3235 goto exit;
3236 #endif
3237 }
3238
3239 exit:
3240 return ret;
3241 }
3242
_issue_deauth(struct adapter * padapter,unsigned char * da,unsigned short reason,bool wait_ack)3243 static int _issue_deauth(struct adapter *padapter, unsigned char *da,
3244 unsigned short reason, bool wait_ack)
3245 {
3246 struct xmit_frame *pmgntframe;
3247 struct pkt_attrib *pattrib;
3248 unsigned char *pframe;
3249 struct ieee80211_hdr *pwlanhdr;
3250 __le16 *fctrl;
3251 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
3252 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3253 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3254 int ret = _FAIL;
3255 __le16 le_tmp;
3256
3257 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3258 if (!pmgntframe)
3259 goto exit;
3260
3261 /* update attribute */
3262 pattrib = &pmgntframe->attrib;
3263 update_mgntframe_attrib(padapter, pattrib);
3264 pattrib->retry_ctrl = false;
3265
3266 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3267
3268 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3269 pwlanhdr = (struct ieee80211_hdr *)pframe;
3270
3271 fctrl = &(pwlanhdr->frame_control);
3272 *(fctrl) = 0;
3273
3274 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3275 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3276 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3277
3278 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3279 pmlmeext->mgnt_seq++;
3280 SetFrameSubType(pframe, WIFI_DEAUTH);
3281
3282 pframe += sizeof(struct ieee80211_hdr_3addr);
3283 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3284
3285 le_tmp = cpu_to_le16(reason);
3286 pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3287
3288 pattrib->last_txcmdsz = pattrib->pktlen;
3289
3290
3291 if (wait_ack) {
3292 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3293 } else {
3294 dump_mgntframe(padapter, pmgntframe);
3295 ret = _SUCCESS;
3296 }
3297
3298 exit:
3299 return ret;
3300 }
3301
issue_deauth(struct adapter * padapter,unsigned char * da,unsigned short reason)3302 int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
3303 {
3304 return _issue_deauth(padapter, da, reason, false);
3305 }
3306
issue_deauth_ex(struct adapter * padapter,u8 * da,unsigned short reason,int try_cnt,int wait_ms)3307 int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
3308 int wait_ms)
3309 {
3310 int ret;
3311 int i = 0;
3312
3313 do {
3314 ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
3315
3316 i++;
3317
3318 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3319 break;
3320
3321 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3322 mdelay(wait_ms);
3323
3324 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3325
3326 if (ret != _FAIL) {
3327 ret = _SUCCESS;
3328 #ifndef DBG_XMIT_ACK
3329 goto exit;
3330 #endif
3331 }
3332
3333 exit:
3334 return ret;
3335 }
3336
issue_action_SA_Query(struct adapter * padapter,unsigned char * raddr,unsigned char action,unsigned short tid)3337 void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
3338 {
3339 u8 category = RTW_WLAN_CATEGORY_SA_QUERY;
3340 struct xmit_frame *pmgntframe;
3341 struct pkt_attrib *pattrib;
3342 u8 *pframe;
3343 struct ieee80211_hdr *pwlanhdr;
3344 __le16 *fctrl;
3345 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
3346 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3347 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3348 __le16 le_tmp;
3349
3350 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3351 if (!pmgntframe)
3352 return;
3353
3354 /* update attribute */
3355 pattrib = &pmgntframe->attrib;
3356 update_mgntframe_attrib(padapter, pattrib);
3357
3358 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3359
3360 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3361 pwlanhdr = (struct ieee80211_hdr *)pframe;
3362
3363 fctrl = &(pwlanhdr->frame_control);
3364 *(fctrl) = 0;
3365
3366 if (raddr)
3367 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3368 else
3369 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3370 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3371 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3372
3373 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3374 pmlmeext->mgnt_seq++;
3375 SetFrameSubType(pframe, WIFI_ACTION);
3376
3377 pframe += sizeof(struct ieee80211_hdr_3addr);
3378 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3379
3380 pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
3381 pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
3382
3383 switch (action) {
3384 case 0: /* SA Query req */
3385 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
3386 pmlmeext->sa_query_seq++;
3387 /* send sa query request to AP, AP should reply sa query response in 1 second */
3388 set_sa_query_timer(pmlmeext, 1000);
3389 break;
3390
3391 case 1: /* SA Query rsp */
3392 le_tmp = cpu_to_le16(tid);
3393 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
3394 break;
3395 default:
3396 break;
3397 }
3398
3399 pattrib->last_txcmdsz = pattrib->pktlen;
3400
3401 dump_mgntframe(padapter, pmgntframe);
3402 }
3403
issue_action_BA(struct adapter * padapter,unsigned char * raddr,unsigned char action,unsigned short status)3404 void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
3405 {
3406 u8 category = RTW_WLAN_CATEGORY_BACK;
3407 u16 start_seq;
3408 u16 BA_para_set;
3409 u16 reason_code;
3410 u16 BA_timeout_value;
3411 u16 BA_starting_seqctrl = 0;
3412 enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor;
3413 struct xmit_frame *pmgntframe;
3414 struct pkt_attrib *pattrib;
3415 u8 *pframe;
3416 struct ieee80211_hdr *pwlanhdr;
3417 __le16 *fctrl;
3418 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
3419 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3420 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3421 struct sta_info *psta;
3422 struct sta_priv *pstapriv = &padapter->stapriv;
3423 struct registry_priv *pregpriv = &padapter->registrypriv;
3424 __le16 le_tmp;
3425
3426 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3427 if (!pmgntframe)
3428 return;
3429
3430 /* update attribute */
3431 pattrib = &pmgntframe->attrib;
3432 update_mgntframe_attrib(padapter, pattrib);
3433
3434 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3435
3436 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3437 pwlanhdr = (struct ieee80211_hdr *)pframe;
3438
3439 fctrl = &(pwlanhdr->frame_control);
3440 *(fctrl) = 0;
3441
3442 /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
3443 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3444 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3445 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3446
3447 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3448 pmlmeext->mgnt_seq++;
3449 SetFrameSubType(pframe, WIFI_ACTION);
3450
3451 pframe += sizeof(struct ieee80211_hdr_3addr);
3452 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3453
3454 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3455 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3456
3457 if (category == 3) {
3458 switch (action) {
3459 case 0: /* ADDBA req */
3460 do {
3461 pmlmeinfo->dialogToken++;
3462 } while (pmlmeinfo->dialogToken == 0);
3463 pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
3464
3465 if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) {
3466 /* A-MSDU NOT Supported */
3467 BA_para_set = 0;
3468 /* immediate Block Ack */
3469 BA_para_set |= BIT(1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
3470 /* TID */
3471 BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
3472 /* max buffer size is 8 MSDU */
3473 BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3474 } else {
3475 BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
3476 }
3477 le_tmp = cpu_to_le16(BA_para_set);
3478 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3479
3480 BA_timeout_value = 5000;/* 5ms */
3481 le_tmp = cpu_to_le16(BA_timeout_value);
3482 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3483
3484 /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.mac_address)) != NULL) */
3485 psta = rtw_get_stainfo(pstapriv, raddr);
3486 if (psta) {
3487 start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] % 4096u) + 1;
3488
3489 psta->BA_starting_seqctrl[status & 0x07] = start_seq;
3490
3491 BA_starting_seqctrl = start_seq << 4;
3492 }
3493
3494 le_tmp = cpu_to_le16(BA_starting_seqctrl);
3495 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3496 break;
3497
3498 case 1: /* ADDBA rsp */
3499 pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
3500 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
3501 if (padapter->driver_rx_ampdu_factor != 0xFF)
3502 max_rx_ampdu_factor =
3503 (enum ieee80211_max_ampdu_length_exp)padapter->driver_rx_ampdu_factor;
3504 else
3505 rtw_hal_get_def_var(padapter,
3506 HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
3507
3508 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
3509 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
3510 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
3511 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
3512 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
3513 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
3514 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
3515 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
3516 else
3517 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
3518
3519 if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter) &&
3520 padapter->driver_rx_ampdu_factor == 0xFF) {
3521 /* max buffer size is 8 MSDU */
3522 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3523 BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3524 }
3525
3526 if (pregpriv->ampdu_amsdu == 0)/* disabled */
3527 le_tmp = cpu_to_le16(BA_para_set & ~BIT(0));
3528 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
3529 le_tmp = cpu_to_le16(BA_para_set | BIT(0));
3530 else /* auto */
3531 le_tmp = cpu_to_le16(BA_para_set);
3532
3533 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3534 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
3535 break;
3536 case 2:/* DELBA */
3537 BA_para_set = (status & 0x1F) << 3;
3538 le_tmp = cpu_to_le16(BA_para_set);
3539 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3540
3541 reason_code = 37;
3542 le_tmp = cpu_to_le16(reason_code);
3543 pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3544 break;
3545 default:
3546 break;
3547 }
3548 }
3549
3550 pattrib->last_txcmdsz = pattrib->pktlen;
3551
3552 dump_mgntframe(padapter, pmgntframe);
3553 }
3554
issue_action_BSSCoexistPacket(struct adapter * padapter)3555 static void issue_action_BSSCoexistPacket(struct adapter *padapter)
3556 {
3557 struct list_head *plist, *phead;
3558 unsigned char category, action;
3559 struct xmit_frame *pmgntframe;
3560 struct pkt_attrib *pattrib;
3561 unsigned char *pframe;
3562 struct ieee80211_hdr *pwlanhdr;
3563 __le16 *fctrl;
3564 struct wlan_network *pnetwork = NULL;
3565 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
3566 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3567 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3568 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3569 struct __queue *queue = &(pmlmepriv->scanned_queue);
3570 u8 InfoContent[16] = {0};
3571 u8 ICS[8][15];
3572
3573 if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
3574 return;
3575
3576 if (true == pmlmeinfo->bwmode_updated)
3577 return;
3578
3579 category = RTW_WLAN_CATEGORY_PUBLIC;
3580 action = ACT_PUBLIC_BSSCOEXIST;
3581
3582 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3583 if (!pmgntframe)
3584 return;
3585
3586 /* update attribute */
3587 pattrib = &pmgntframe->attrib;
3588 update_mgntframe_attrib(padapter, pattrib);
3589
3590 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3591
3592 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3593 pwlanhdr = (struct ieee80211_hdr *)pframe;
3594
3595 fctrl = &(pwlanhdr->frame_control);
3596 *(fctrl) = 0;
3597
3598 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3599 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3600 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3601
3602 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3603 pmlmeext->mgnt_seq++;
3604 SetFrameSubType(pframe, WIFI_ACTION);
3605
3606 pframe += sizeof(struct ieee80211_hdr_3addr);
3607 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3608
3609 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3610 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3611
3612
3613 /* */
3614 if (pmlmepriv->num_FortyMHzIntolerant > 0) {
3615 u8 iedata = 0;
3616
3617 iedata |= BIT(2);/* 20 MHz BSS Width Request */
3618
3619 pframe = rtw_set_ie(pframe, WLAN_EID_BSS_COEX_2040, 1, &iedata, &(pattrib->pktlen));
3620
3621 }
3622
3623
3624 /* */
3625 memset(ICS, 0, sizeof(ICS));
3626 if (pmlmepriv->num_sta_no_ht > 0) {
3627 int i;
3628
3629 spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3630
3631 phead = get_list_head(queue);
3632 plist = get_next(phead);
3633
3634 while (1) {
3635 int len;
3636 u8 *p;
3637 struct wlan_bssid_ex *pbss_network;
3638
3639 if (phead == plist)
3640 break;
3641
3642 pnetwork = container_of(plist, struct wlan_network, list);
3643
3644 plist = get_next(plist);
3645
3646 pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
3647
3648 p = rtw_get_ie(pbss_network->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->ie_length - _FIXED_IE_LENGTH_);
3649 if (!p || len == 0) {/* non-HT */
3650
3651 if (pbss_network->configuration.ds_config <= 0)
3652 continue;
3653
3654 ICS[0][pbss_network->configuration.ds_config] = 1;
3655
3656 if (ICS[0][0] == 0)
3657 ICS[0][0] = 1;
3658 }
3659
3660 }
3661
3662 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
3663
3664
3665 for (i = 0; i < 8; i++) {
3666 int j, k = 0;
3667
3668 if (ICS[i][0] != 1)
3669 continue;
3670
3671 InfoContent[k] = i;
3672 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
3673 k++;
3674
3675 for (j = 1; j <= 14; j++) {
3676 if (ICS[i][j] != 1)
3677 continue;
3678
3679 if (k < 16) {
3680 InfoContent[k] = j; /* channel number */
3681 /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
3682 k++;
3683 }
3684 }
3685
3686 pframe = rtw_set_ie(pframe, WLAN_EID_BSS_INTOLERANT_CHL_REPORT, k, InfoContent, &(pattrib->pktlen));
3687
3688 }
3689
3690 }
3691
3692
3693 pattrib->last_txcmdsz = pattrib->pktlen;
3694
3695 dump_mgntframe(padapter, pmgntframe);
3696 }
3697
send_delba(struct adapter * padapter,u8 initiator,u8 * addr)3698 unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
3699 {
3700 struct sta_priv *pstapriv = &padapter->stapriv;
3701 struct sta_info *psta = NULL;
3702 /* struct recv_reorder_ctrl *preorder_ctrl; */
3703 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3704 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3705 u16 tid;
3706
3707 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
3708 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3709 return _SUCCESS;
3710
3711 psta = rtw_get_stainfo(pstapriv, addr);
3712 if (!psta)
3713 return _SUCCESS;
3714
3715 if (initiator == 0) {/* recipient */
3716 for (tid = 0; tid < MAXTID; tid++) {
3717 if (psta->recvreorder_ctrl[tid].enable) {
3718 issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
3719 psta->recvreorder_ctrl[tid].enable = false;
3720 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
3721 }
3722 }
3723 } else if (initiator == 1) {/* originator */
3724 for (tid = 0; tid < MAXTID; tid++) {
3725 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
3726 issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
3727 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3728 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3729
3730 }
3731 }
3732 }
3733
3734 return _SUCCESS;
3735
3736 }
3737
send_beacon(struct adapter * padapter)3738 unsigned int send_beacon(struct adapter *padapter)
3739 {
3740 u8 bxmitok = false;
3741 int issue = 0;
3742 int poll = 0;
3743
3744 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
3745 rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
3746 do {
3747 issue_beacon(padapter, 100);
3748 issue++;
3749 do {
3750 cond_resched();
3751 rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
3752 poll++;
3753 } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
3754
3755 } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
3756
3757 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
3758 return _FAIL;
3759
3760 if (!bxmitok)
3761 return _FAIL;
3762 else
3763 return _SUCCESS;
3764 }
3765
3766 /* Following are some utility functions for WiFi MLME */
3767
site_survey(struct adapter * padapter)3768 void site_survey(struct adapter *padapter)
3769 {
3770 unsigned char survey_channel = 0, val8;
3771 enum rt_scan_type ScanType = SCAN_PASSIVE;
3772 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3773 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3774 u32 initialgain = 0;
3775 u32 channel_scan_time_ms = 0;
3776
3777 {
3778 struct rtw_ieee80211_channel *ch;
3779
3780 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
3781 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
3782 survey_channel = ch->hw_value;
3783 ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
3784 }
3785 }
3786
3787 if (survey_channel != 0) {
3788 /* PAUSE 4-AC Queue when site_survey */
3789 /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3790 /* val8 |= 0x0f; */
3791 /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3792 if (pmlmeext->sitesurvey_res.channel_idx == 0) {
3793 #ifdef DBG_FIXED_CHAN
3794 if (pmlmeext->fixed_chan != 0xff)
3795 set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3796 else
3797 #endif
3798 set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3799 } else {
3800 #ifdef DBG_FIXED_CHAN
3801 if (pmlmeext->fixed_chan != 0xff)
3802 r8723bs_select_channel(padapter, pmlmeext->fixed_chan);
3803 else
3804 #endif
3805 r8723bs_select_channel(padapter, survey_channel);
3806 }
3807
3808 if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
3809 {
3810 int i;
3811
3812 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
3813 if (!pmlmeext->sitesurvey_res.ssid[i].ssid_length)
3814 continue;
3815
3816 /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
3817 if (padapter->registrypriv.wifi_spec)
3818 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
3819 else
3820 issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
3821
3822 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
3823 }
3824
3825 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
3826 /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
3827 if (padapter->registrypriv.wifi_spec)
3828 issue_probereq(padapter, NULL, NULL);
3829 else
3830 issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
3831 issue_probereq(padapter, NULL, NULL);
3832 }
3833 }
3834 }
3835
3836 channel_scan_time_ms = pmlmeext->chan_scan_time;
3837
3838 set_survey_timer(pmlmeext, channel_scan_time_ms);
3839 } else {
3840
3841 /* channel number is 0 or this channel is not valid. */
3842
3843 {
3844 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
3845
3846 /* switch back to the original channel */
3847 /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
3848
3849 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
3850
3851 /* flush 4-AC Queue after site_survey */
3852 /* val8 = 0; */
3853 /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3854
3855 /* config MSR */
3856 set_msr(padapter, (pmlmeinfo->state & 0x3));
3857
3858 initialgain = 0xff; /* restore RX GAIN */
3859 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
3860 /* turn on dynamic functions */
3861 Restore_DM_Func_Flag(padapter);
3862 /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
3863
3864 if (is_client_associated_to_ap(padapter))
3865 issue_nulldata(padapter, NULL, 0, 3, 500);
3866
3867 val8 = 0; /* survey done */
3868 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3869
3870 report_surveydone_event(padapter);
3871
3872 pmlmeext->chan_scan_time = SURVEY_TO;
3873 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
3874
3875 issue_action_BSSCoexistPacket(padapter);
3876 issue_action_BSSCoexistPacket(padapter);
3877 issue_action_BSSCoexistPacket(padapter);
3878 }
3879 }
3880
3881 return;
3882
3883 }
3884
3885 /* collect bss info from Beacon and Probe request/response frames. */
collect_bss_info(struct adapter * padapter,union recv_frame * precv_frame,struct wlan_bssid_ex * bssid)3886 u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
3887 {
3888 int i;
3889 u32 len;
3890 u8 *p;
3891 u16 val16, subtype;
3892 u8 *pframe = precv_frame->u.hdr.rx_data;
3893 u32 packet_len = precv_frame->u.hdr.len;
3894 u8 ie_offset;
3895 struct registry_priv *pregistrypriv = &padapter->registrypriv;
3896 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3897 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3898 __le32 le32_tmp;
3899
3900 len = packet_len - sizeof(struct ieee80211_hdr_3addr);
3901
3902 if (len > MAX_IE_SZ)
3903 return _FAIL;
3904
3905 memset(bssid, 0, sizeof(struct wlan_bssid_ex));
3906
3907 subtype = GetFrameSubType(pframe);
3908
3909 if (subtype == WIFI_BEACON) {
3910 bssid->reserved[0] = 1;
3911 ie_offset = _BEACON_IE_OFFSET_;
3912 } else {
3913 /* FIXME : more type */
3914 if (subtype == WIFI_PROBERSP) {
3915 ie_offset = _PROBERSP_IE_OFFSET_;
3916 bssid->reserved[0] = 3;
3917 } else if (subtype == WIFI_PROBEREQ) {
3918 ie_offset = _PROBEREQ_IE_OFFSET_;
3919 bssid->reserved[0] = 2;
3920 } else {
3921 bssid->reserved[0] = 0;
3922 ie_offset = _FIXED_IE_LENGTH_;
3923 }
3924 }
3925
3926 bssid->length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
3927
3928 /* below is to copy the information element */
3929 bssid->ie_length = len;
3930 memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
3931
3932 /* get the signal strength */
3933 bssid->rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /* in dBM.raw data */
3934 bssid->phy_info.signal_quality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
3935 bssid->phy_info.signal_strength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
3936
3937 /* checking SSID */
3938 p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SSID, &len, bssid->ie_length - ie_offset);
3939 if (!p)
3940 return _FAIL;
3941
3942 if (*(p + 1)) {
3943 if (len > NDIS_802_11_LENGTH_SSID)
3944 return _FAIL;
3945
3946 memcpy(bssid->ssid.ssid, (p + 2), *(p + 1));
3947 bssid->ssid.ssid_length = *(p + 1);
3948 } else
3949 bssid->ssid.ssid_length = 0;
3950
3951 memset(bssid->supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
3952
3953 /* checking rate info... */
3954 i = 0;
3955 p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->ie_length - ie_offset);
3956 if (p) {
3957 if (len > NDIS_802_11_LENGTH_RATES_EX)
3958 return _FAIL;
3959
3960 memcpy(bssid->supported_rates, (p + 2), len);
3961 i = len;
3962 }
3963
3964 p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->ie_length - ie_offset);
3965 if (p) {
3966 if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
3967 return _FAIL;
3968
3969 memcpy(bssid->supported_rates + i, (p + 2), len);
3970 }
3971
3972 bssid->network_type_in_use = Ndis802_11OFDM24;
3973
3974 if (bssid->ie_length < 12)
3975 return _FAIL;
3976
3977 /* Checking for ds_config */
3978 p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->ie_length - ie_offset);
3979
3980 bssid->configuration.ds_config = 0;
3981 bssid->configuration.length = 0;
3982
3983 if (p) {
3984 bssid->configuration.ds_config = *(p + 2);
3985 } else {
3986 /* In 5G, some ap do not have DSSET IE */
3987 /* checking HT info for channel */
3988 p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - ie_offset);
3989 if (p) {
3990 struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
3991
3992 bssid->configuration.ds_config = HT_info->primary_channel;
3993 } else { /* use current channel */
3994 bssid->configuration.ds_config = rtw_get_oper_ch(padapter);
3995 }
3996 }
3997
3998 memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->ies), 2);
3999 bssid->configuration.beacon_period = le32_to_cpu(le32_tmp);
4000
4001 val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
4002
4003 if (val16 & BIT(0)) {
4004 bssid->infrastructure_mode = Ndis802_11Infrastructure;
4005 memcpy(bssid->mac_address, GetAddr2Ptr(pframe), ETH_ALEN);
4006 } else {
4007 bssid->infrastructure_mode = Ndis802_11IBSS;
4008 memcpy(bssid->mac_address, GetAddr3Ptr(pframe), ETH_ALEN);
4009 }
4010
4011 if (val16 & BIT(4))
4012 bssid->privacy = 1;
4013 else
4014 bssid->privacy = 0;
4015
4016 bssid->configuration.atim_window = 0;
4017
4018 /* 20/40 BSS Coexistence check */
4019 if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) {
4020 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4021
4022 p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->ie_length - ie_offset);
4023 if (p && len > 0) {
4024 struct HT_caps_element *pHT_caps;
4025
4026 pHT_caps = (struct HT_caps_element *)(p + 2);
4027
4028 if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
4029 pmlmepriv->num_FortyMHzIntolerant++;
4030 } else
4031 pmlmepriv->num_sta_no_ht++;
4032 }
4033
4034 /* mark bss info receiving from nearby channel as signal_quality 101 */
4035 if (bssid->configuration.ds_config != rtw_get_oper_ch(padapter))
4036 bssid->phy_info.signal_quality = 101;
4037
4038 return _SUCCESS;
4039 }
4040
start_create_ibss(struct adapter * padapter)4041 void start_create_ibss(struct adapter *padapter)
4042 {
4043 unsigned short caps;
4044 u8 val8;
4045 u8 join_type;
4046 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4047 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4048 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4049
4050 pmlmeext->cur_channel = (u8)pnetwork->configuration.ds_config;
4051 pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
4052
4053 /* update wireless mode */
4054 update_wireless_mode(padapter);
4055
4056 /* update capability */
4057 caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4058 update_capinfo(padapter, caps);
4059 if (caps&WLAN_CAPABILITY_IBSS) {/* adhoc master */
4060 val8 = 0xcf;
4061 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4062
4063 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
4064
4065 /* switch channel */
4066 /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4067 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4068
4069 beacon_timing_control(padapter);
4070
4071 /* set msr to WIFI_FW_ADHOC_STATE */
4072 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4073 set_msr(padapter, (pmlmeinfo->state & 0x3));
4074
4075 /* issue beacon */
4076 if (send_beacon(padapter) == _FAIL) {
4077 report_join_res(padapter, -1);
4078 pmlmeinfo->state = WIFI_FW_NULL_STATE;
4079 } else {
4080 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.mac_address);
4081 join_type = 0;
4082 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4083
4084 report_join_res(padapter, 1);
4085 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4086 rtw_indicate_connect(padapter);
4087 }
4088 } else {
4089 return;
4090 }
4091 /* update bc/mc sta_info */
4092 update_bmc_sta(padapter);
4093
4094 }
4095
start_clnt_join(struct adapter * padapter)4096 void start_clnt_join(struct adapter *padapter)
4097 {
4098 unsigned short caps;
4099 u8 val8;
4100 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4101 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4102 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4103 int beacon_timeout;
4104
4105 /* update wireless mode */
4106 update_wireless_mode(padapter);
4107
4108 /* update capability */
4109 caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4110 update_capinfo(padapter, caps);
4111 if (caps&WLAN_CAPABILITY_ESS) {
4112 set_msr(padapter, WIFI_FW_STATION_STATE);
4113
4114 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
4115
4116 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4117
4118 /* Because of AP's not receiving deauth before
4119 * AP may: 1)not response auth or 2)deauth us after link is complete
4120 * issue deauth before issuing auth to deal with the situation
4121 *
4122 * Commented by Albert 2012/07/21
4123 * For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it.
4124 */
4125 {
4126 /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
4127 issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
4128 }
4129
4130 /* here wait for receiving the beacon to start auth */
4131 /* and enable a timer */
4132 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
4133 set_link_timer(pmlmeext, beacon_timeout);
4134 _set_timer(&padapter->mlmepriv.assoc_timer,
4135 (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
4136
4137 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
4138 } else if (caps&WLAN_CAPABILITY_IBSS) { /* adhoc client */
4139 set_msr(padapter, WIFI_FW_ADHOC_STATE);
4140
4141 val8 = 0xcf;
4142 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4143
4144 beacon_timing_control(padapter);
4145
4146 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4147
4148 report_join_res(padapter, 1);
4149 } else {
4150 return;
4151 }
4152
4153 }
4154
start_clnt_auth(struct adapter * padapter)4155 void start_clnt_auth(struct adapter *padapter)
4156 {
4157 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4158 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4159
4160 timer_delete_sync(&pmlmeext->link_timer);
4161
4162 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4163 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4164
4165 pmlmeinfo->auth_seq = 1;
4166 pmlmeinfo->reauth_count = 0;
4167 pmlmeinfo->reassoc_count = 0;
4168 pmlmeinfo->link_count = 0;
4169 pmlmeext->retry = 0;
4170
4171
4172 netdev_dbg(padapter->pnetdev, "start auth\n");
4173 issue_auth(padapter, NULL, 0);
4174
4175 set_link_timer(pmlmeext, REAUTH_TO);
4176
4177 }
4178
4179
start_clnt_assoc(struct adapter * padapter)4180 void start_clnt_assoc(struct adapter *padapter)
4181 {
4182 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4183 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4184
4185 timer_delete_sync(&pmlmeext->link_timer);
4186
4187 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4188 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4189
4190 issue_assocreq(padapter);
4191
4192 set_link_timer(pmlmeext, REASSOC_TO);
4193 }
4194
receive_disconnect(struct adapter * padapter,unsigned char * MacAddr,unsigned short reason)4195 unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4196 {
4197 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4198 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4199
4200 /* check A3 */
4201 if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
4202 return _SUCCESS;
4203
4204 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4205 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4206 pmlmeinfo->state = WIFI_FW_NULL_STATE;
4207 report_del_sta_event(padapter, MacAddr, reason);
4208
4209 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4210 pmlmeinfo->state = WIFI_FW_NULL_STATE;
4211 report_join_res(padapter, -2);
4212 }
4213 }
4214
4215 return _SUCCESS;
4216 }
4217
process_80211d(struct adapter * padapter,struct wlan_bssid_ex * bssid)4218 static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
4219 {
4220 struct registry_priv *pregistrypriv;
4221 struct mlme_ext_priv *pmlmeext;
4222 struct rt_channel_info *chplan_new;
4223 u8 channel;
4224 u8 i;
4225
4226
4227 pregistrypriv = &padapter->registrypriv;
4228 pmlmeext = &padapter->mlmeextpriv;
4229
4230 /* Adjust channel plan by AP Country IE */
4231 if (pregistrypriv->enable80211d &&
4232 (!pmlmeext->update_channel_plan_by_ap_done)) {
4233 u8 *ie, *p;
4234 u32 len;
4235 struct rt_channel_plan chplan_ap;
4236 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4237 u8 country[4];
4238 u8 fcn; /* first channel number */
4239 u8 noc; /* number of channel */
4240 u8 j, k;
4241
4242 ie = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
4243 if (!ie)
4244 return;
4245 if (len < 6)
4246 return;
4247
4248 ie += 2;
4249 p = ie;
4250 ie += len;
4251
4252 memset(country, 0, 4);
4253 memcpy(country, p, 3);
4254 p += 3;
4255
4256 i = 0;
4257 while ((ie - p) >= 3) {
4258 fcn = *(p++);
4259 noc = *(p++);
4260 p++;
4261
4262 for (j = 0; j < noc; j++) {
4263 if (fcn <= 14)
4264 channel = fcn + j; /* 2.4 GHz */
4265 else
4266 channel = fcn + j*4; /* 5 GHz */
4267
4268 chplan_ap.Channel[i++] = channel;
4269 }
4270 }
4271 chplan_ap.Len = i;
4272
4273 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4274
4275 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4276 chplan_new = pmlmeext->channel_set;
4277
4278 i = j = k = 0;
4279 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4280 do {
4281 if ((i == MAX_CHANNEL_NUM) ||
4282 (chplan_sta[i].ChannelNum == 0) ||
4283 (chplan_sta[i].ChannelNum > 14))
4284 break;
4285
4286 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
4287 break;
4288
4289 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
4290 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4291 chplan_new[k].ScanType = SCAN_ACTIVE;
4292 i++;
4293 j++;
4294 k++;
4295 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
4296 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4297 chplan_new[k].ScanType = SCAN_PASSIVE;
4298 i++;
4299 k++;
4300 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
4301 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4302 chplan_new[k].ScanType = SCAN_ACTIVE;
4303 j++;
4304 k++;
4305 }
4306 } while (1);
4307
4308 /* change AP not support channel to Passive scan */
4309 while ((i < MAX_CHANNEL_NUM) &&
4310 (chplan_sta[i].ChannelNum != 0) &&
4311 (chplan_sta[i].ChannelNum <= 14)) {
4312
4313 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4314 chplan_new[k].ScanType = SCAN_PASSIVE;
4315 i++;
4316 k++;
4317 }
4318
4319 /* add channel AP supported */
4320 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
4321 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4322 chplan_new[k].ScanType = SCAN_ACTIVE;
4323 j++;
4324 k++;
4325 }
4326 } else {
4327 /* keep original STA 2.4G channel plan */
4328 while ((i < MAX_CHANNEL_NUM) &&
4329 (chplan_sta[i].ChannelNum != 0) &&
4330 (chplan_sta[i].ChannelNum <= 14)) {
4331 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4332 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4333 i++;
4334 k++;
4335 }
4336
4337 /* skip AP 2.4G channel plan */
4338 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
4339 j++;
4340 }
4341
4342 pmlmeext->update_channel_plan_by_ap_done = 1;
4343 }
4344
4345 /* If channel is used by AP, set channel scan type to active */
4346 channel = bssid->configuration.ds_config;
4347 chplan_new = pmlmeext->channel_set;
4348 i = 0;
4349 while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
4350 if (chplan_new[i].ChannelNum == channel) {
4351 if (chplan_new[i].ScanType == SCAN_PASSIVE)
4352 chplan_new[i].ScanType = SCAN_ACTIVE;
4353 break;
4354 }
4355 i++;
4356 }
4357 }
4358
4359 /* Following are the functions to report events */
4360
report_survey_event(struct adapter * padapter,union recv_frame * precv_frame)4361 void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
4362 {
4363 struct cmd_obj *pcmd_obj;
4364 u8 *pevtcmd;
4365 u32 cmdsz;
4366 struct survey_event *psurvey_evt;
4367 struct C2HEvent_Header *pc2h_evt_hdr;
4368 struct mlme_ext_priv *pmlmeext;
4369 struct cmd_priv *pcmdpriv;
4370 /* u8 *pframe = precv_frame->u.hdr.rx_data; */
4371 /* uint len = precv_frame->u.hdr.len; */
4372
4373 if (!padapter)
4374 return;
4375
4376 pmlmeext = &padapter->mlmeextpriv;
4377 pcmdpriv = &padapter->cmdpriv;
4378
4379 pcmd_obj = kzalloc_obj(*pcmd_obj, GFP_ATOMIC);
4380 if (!pcmd_obj)
4381 return;
4382
4383 cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
4384 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4385 if (!pevtcmd) {
4386 kfree(pcmd_obj);
4387 return;
4388 }
4389
4390 INIT_LIST_HEAD(&pcmd_obj->list);
4391
4392 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4393 pcmd_obj->cmdsz = cmdsz;
4394 pcmd_obj->parmbuf = pevtcmd;
4395
4396 pcmd_obj->rsp = NULL;
4397 pcmd_obj->rspsz = 0;
4398
4399 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4400 pc2h_evt_hdr->len = sizeof(struct survey_event);
4401 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4402 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4403
4404 psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4405
4406 if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
4407 kfree(pcmd_obj);
4408 kfree(pevtcmd);
4409 return;
4410 }
4411
4412 process_80211d(padapter, &psurvey_evt->bss);
4413
4414 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4415
4416 pmlmeext->sitesurvey_res.bss_cnt++;
4417
4418 return;
4419
4420 }
4421
report_surveydone_event(struct adapter * padapter)4422 void report_surveydone_event(struct adapter *padapter)
4423 {
4424 struct cmd_obj *pcmd_obj;
4425 u8 *pevtcmd;
4426 u32 cmdsz;
4427 struct surveydone_event *psurveydone_evt;
4428 struct C2HEvent_Header *pc2h_evt_hdr;
4429 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4430 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4431
4432 pcmd_obj = kzalloc_obj(*pcmd_obj, GFP_ATOMIC);
4433 if (!pcmd_obj)
4434 return;
4435
4436 cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
4437 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4438 if (!pevtcmd) {
4439 kfree(pcmd_obj);
4440 return;
4441 }
4442
4443 INIT_LIST_HEAD(&pcmd_obj->list);
4444
4445 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4446 pcmd_obj->cmdsz = cmdsz;
4447 pcmd_obj->parmbuf = pevtcmd;
4448
4449 pcmd_obj->rsp = NULL;
4450 pcmd_obj->rspsz = 0;
4451
4452 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4453 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4454 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4455 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4456
4457 psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4458 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4459
4460 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4461
4462 return;
4463
4464 }
4465
report_join_res(struct adapter * padapter,int res)4466 void report_join_res(struct adapter *padapter, int res)
4467 {
4468 struct cmd_obj *pcmd_obj;
4469 u8 *pevtcmd;
4470 u32 cmdsz;
4471 struct joinbss_event *pjoinbss_evt;
4472 struct C2HEvent_Header *pc2h_evt_hdr;
4473 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4474 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4475 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4476
4477 pcmd_obj = kzalloc_obj(*pcmd_obj, GFP_ATOMIC);
4478 if (!pcmd_obj)
4479 return;
4480
4481 cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
4482 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4483 if (!pevtcmd) {
4484 kfree(pcmd_obj);
4485 return;
4486 }
4487
4488 INIT_LIST_HEAD(&pcmd_obj->list);
4489
4490 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4491 pcmd_obj->cmdsz = cmdsz;
4492 pcmd_obj->parmbuf = pevtcmd;
4493
4494 pcmd_obj->rsp = NULL;
4495 pcmd_obj->rspsz = 0;
4496
4497 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4498 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4499 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4500 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4501
4502 pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4503 memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
4504 pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = res;
4505
4506
4507 rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
4508
4509
4510 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4511
4512 return;
4513
4514 }
4515
report_wmm_edca_update(struct adapter * padapter)4516 void report_wmm_edca_update(struct adapter *padapter)
4517 {
4518 struct cmd_obj *pcmd_obj;
4519 u8 *pevtcmd;
4520 u32 cmdsz;
4521 struct wmm_event *pwmm_event;
4522 struct C2HEvent_Header *pc2h_evt_hdr;
4523 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4524 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4525
4526 pcmd_obj = kzalloc_obj(*pcmd_obj, GFP_ATOMIC);
4527 if (!pcmd_obj)
4528 return;
4529
4530 cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
4531 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4532 if (!pevtcmd) {
4533 kfree(pcmd_obj);
4534 return;
4535 }
4536
4537 INIT_LIST_HEAD(&pcmd_obj->list);
4538
4539 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4540 pcmd_obj->cmdsz = cmdsz;
4541 pcmd_obj->parmbuf = pevtcmd;
4542
4543 pcmd_obj->rsp = NULL;
4544 pcmd_obj->rspsz = 0;
4545
4546 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4547 pc2h_evt_hdr->len = sizeof(struct wmm_event);
4548 pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);
4549 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4550
4551 pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4552 pwmm_event->wmm = 0;
4553
4554 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4555
4556 return;
4557
4558 }
4559
report_del_sta_event(struct adapter * padapter,unsigned char * MacAddr,unsigned short reason)4560 void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4561 {
4562 struct cmd_obj *pcmd_obj;
4563 u8 *pevtcmd;
4564 u32 cmdsz;
4565 struct sta_info *psta;
4566 int mac_id;
4567 struct stadel_event *pdel_sta_evt;
4568 struct C2HEvent_Header *pc2h_evt_hdr;
4569 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4570 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4571
4572 pcmd_obj = kzalloc_obj(*pcmd_obj, GFP_ATOMIC);
4573 if (!pcmd_obj)
4574 return;
4575
4576 cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
4577 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4578 if (!pevtcmd) {
4579 kfree(pcmd_obj);
4580 return;
4581 }
4582
4583 INIT_LIST_HEAD(&pcmd_obj->list);
4584
4585 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4586 pcmd_obj->cmdsz = cmdsz;
4587 pcmd_obj->parmbuf = pevtcmd;
4588
4589 pcmd_obj->rsp = NULL;
4590 pcmd_obj->rspsz = 0;
4591
4592 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4593 pc2h_evt_hdr->len = sizeof(struct stadel_event);
4594 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4595 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4596
4597 pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4598 memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
4599 memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
4600
4601
4602 psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
4603 if (psta)
4604 mac_id = (int)psta->mac_id;
4605 else
4606 mac_id = (-1);
4607
4608 pdel_sta_evt->mac_id = mac_id;
4609
4610 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4611 }
4612
report_add_sta_event(struct adapter * padapter,unsigned char * MacAddr,int cam_idx)4613 void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
4614 {
4615 struct cmd_obj *pcmd_obj;
4616 u8 *pevtcmd;
4617 u32 cmdsz;
4618 struct stassoc_event *padd_sta_evt;
4619 struct C2HEvent_Header *pc2h_evt_hdr;
4620 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4621 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4622
4623 pcmd_obj = kzalloc_obj(*pcmd_obj, GFP_ATOMIC);
4624 if (!pcmd_obj)
4625 return;
4626
4627 cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
4628 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4629 if (!pevtcmd) {
4630 kfree(pcmd_obj);
4631 return;
4632 }
4633
4634 INIT_LIST_HEAD(&pcmd_obj->list);
4635
4636 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4637 pcmd_obj->cmdsz = cmdsz;
4638 pcmd_obj->parmbuf = pevtcmd;
4639
4640 pcmd_obj->rsp = NULL;
4641 pcmd_obj->rspsz = 0;
4642
4643 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4644 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4645 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4646 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4647
4648 padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4649 memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
4650 padd_sta_evt->cam_id = cam_idx;
4651
4652 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4653 }
4654
4655 /* Following are the event callback functions */
4656
4657 /* for sta/adhoc mode */
update_sta_info(struct adapter * padapter,struct sta_info * psta)4658 void update_sta_info(struct adapter *padapter, struct sta_info *psta)
4659 {
4660 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4661 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4662 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4663
4664 /* ERP */
4665 VCS_update(padapter, psta);
4666
4667 /* HT */
4668 if (pmlmepriv->htpriv.ht_option) {
4669 psta->htpriv.ht_option = true;
4670
4671 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4672
4673 psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;
4674
4675 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
4676 psta->htpriv.sgi_20m = true;
4677
4678 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
4679 psta->htpriv.sgi_40m = true;
4680
4681 psta->qos_option = true;
4682
4683 psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
4684 psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
4685 psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
4686
4687 memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct ieee80211_ht_cap));
4688 } else {
4689 psta->htpriv.ht_option = false;
4690
4691 psta->htpriv.ampdu_enable = false;
4692
4693 psta->htpriv.sgi_20m = false;
4694 psta->htpriv.sgi_40m = false;
4695 psta->qos_option = false;
4696
4697 }
4698
4699 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
4700
4701 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
4702 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
4703
4704 psta->bw_mode = pmlmeext->cur_bwmode;
4705
4706 /* QoS */
4707 if (pmlmepriv->qospriv.qos_option)
4708 psta->qos_option = true;
4709
4710 update_ldpc_stbc_cap(psta);
4711
4712 spin_lock_bh(&psta->lock);
4713 psta->state = _FW_LINKED;
4714 spin_unlock_bh(&psta->lock);
4715
4716 }
4717
rtw_mlmeext_disconnect(struct adapter * padapter)4718 static void rtw_mlmeext_disconnect(struct adapter *padapter)
4719 {
4720 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4721 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4722 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4723 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4724
4725 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
4726
4727 /* For safety, prevent from keeping macid sleep.
4728 * If we can sure all power mode enter/leave are paired,
4729 * this check can be removed.
4730 * Lucas@20131113
4731 */
4732 /* wakeup macid after disconnect. */
4733 {
4734 struct sta_info *psta;
4735
4736 psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
4737 if (psta)
4738 rtw_hal_macid_wakeup(padapter, psta->mac_id);
4739 }
4740
4741 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
4742 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4743
4744 /* set MSR to no link state -> infra. mode */
4745 set_msr(padapter, _HW_STATE_STATION_);
4746
4747 pmlmeinfo->state = WIFI_FW_NULL_STATE;
4748
4749 /* switch to the 20M Hz mode after disconnect */
4750 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
4751 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4752
4753 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4754
4755 flush_all_cam_entry(padapter);
4756
4757 timer_delete_sync(&pmlmeext->link_timer);
4758
4759 /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */
4760 pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
4761 pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
4762
4763 }
4764
mlmeext_joinbss_event_callback(struct adapter * padapter,int join_res)4765 void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
4766 {
4767 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4768 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4769 struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
4770 struct sta_priv *pstapriv = &padapter->stapriv;
4771 u8 join_type;
4772 struct sta_info *psta;
4773
4774 if (join_res < 0) {
4775 join_type = 1;
4776 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4777 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4778
4779 return;
4780 }
4781
4782 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
4783 /* update bc/mc sta_info */
4784 update_bmc_sta(padapter);
4785
4786
4787 /* turn on dynamic functions */
4788 Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
4789
4790 /* update IOT-related issue */
4791 update_IOT_info(padapter);
4792
4793 rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->supported_rates);
4794
4795 /* BCN interval */
4796 rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
4797
4798 /* update capability */
4799 update_capinfo(padapter, pmlmeinfo->capability);
4800
4801 /* WMM, Update EDCA param */
4802 WMMOnAssocRsp(padapter);
4803
4804 /* HT */
4805 HTOnAssocRsp(padapter);
4806
4807 /* Set cur_channel&cur_bwmode&cur_ch_offset */
4808 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4809
4810 psta = rtw_get_stainfo(pstapriv, cur_network->mac_address);
4811 if (psta) { /* only for infra. mode */
4812
4813 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4814
4815 psta->wireless_mode = pmlmeext->cur_wireless_mode;
4816
4817 /* set per sta rate after updating HT cap. */
4818 set_sta_rate(padapter, psta);
4819
4820 rtw_sta_media_status_rpt(padapter, psta, 1);
4821
4822 /*
4823 * wakeup macid after join bss successfully to ensure
4824 * the subsequent data frames can be sent out normally
4825 */
4826 rtw_hal_macid_wakeup(padapter, psta->mac_id);
4827 }
4828
4829 join_type = 2;
4830 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4831
4832 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4833 /* correcting TSF */
4834 correct_TSF(padapter, pmlmeext);
4835
4836 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
4837 }
4838
4839 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
4840 }
4841
4842 /* currently only adhoc mode will go here */
mlmeext_sta_add_event_callback(struct adapter * padapter,struct sta_info * psta)4843 void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
4844 {
4845 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
4846 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4847 u8 join_type;
4848
4849 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4850 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */
4851
4852 /* nothing to do */
4853 } else { /* adhoc client */
4854 /* update TSF Value */
4855 /* update_TSF(pmlmeext, pframe, len); */
4856
4857 /* correcting TSF */
4858 correct_TSF(padapter, pmlmeext);
4859
4860 /* start beacon */
4861 if (send_beacon(padapter) == _FAIL) {
4862 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
4863
4864 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
4865
4866 return;
4867 }
4868
4869 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4870
4871 }
4872
4873 join_type = 2;
4874 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4875 }
4876
4877 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4878
4879 psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
4880 memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
4881
4882 /* update adhoc sta_info */
4883 update_sta_info(padapter, psta);
4884
4885 rtw_hal_update_sta_rate_mask(padapter, psta);
4886
4887 /* ToDo: HT for Ad-hoc */
4888 psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
4889 psta->raid = networktype_to_raid_ex(padapter, psta);
4890
4891 /* rate radaptive */
4892 Update_RA_Entry(padapter, psta);
4893 }
4894
mlmeext_sta_del_event_callback(struct adapter * padapter)4895 void mlmeext_sta_del_event_callback(struct adapter *padapter)
4896 {
4897 if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
4898 rtw_mlmeext_disconnect(padapter);
4899 }
4900
4901 /* Following are the functions for the timer handlers */
4902
_linked_info_dump(struct adapter * padapter)4903 void _linked_info_dump(struct adapter *padapter)
4904 {
4905 int i;
4906 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4907 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4908 int UndecoratedSmoothedPWDB;
4909 struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
4910
4911 if (padapter->bLinkInfoDump) {
4912
4913 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
4914 rtw_hal_get_def_var(padapter,
4915 HAL_DEF_UNDERCORATEDSMOOTHEDPWDB,
4916 &UndecoratedSmoothedPWDB);
4917
4918 for (i = 0; i < NUM_STA; i++) {
4919 if (pdvobj->macid[i]) {
4920 if (i != 1) /* skip bc/mc sta */
4921 /* tx info ============ */
4922 rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);
4923 }
4924 }
4925 }
4926 }
4927
chk_ap_is_alive(struct adapter * padapter,struct sta_info * psta)4928 static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
4929 {
4930 u8 ret = false;
4931
4932 if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
4933 && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
4934 && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
4935 ) {
4936 ret = false;
4937 } else {
4938 ret = true;
4939 }
4940
4941 sta_update_last_rx_pkts(psta);
4942
4943 return ret;
4944 }
4945
linked_status_chk(struct adapter * padapter)4946 void linked_status_chk(struct adapter *padapter)
4947 {
4948 u32 i;
4949 struct sta_info *psta;
4950 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
4951 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4952 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4953 struct sta_priv *pstapriv = &padapter->stapriv;
4954
4955 if (is_client_associated_to_ap(padapter)) {
4956 /* linked infrastructure client mode */
4957
4958 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
4959 int rx_chk_limit;
4960 int link_count_limit;
4961
4962 #if defined(DBG_ROAMING_TEST)
4963 rx_chk_limit = 1;
4964 #else
4965 rx_chk_limit = 8;
4966 #endif
4967 link_count_limit = 7; /* 16 sec */
4968
4969 /* Marked by Kurt 20130715 */
4970 /* For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, */
4971 /* so we could not check rx limit that strictly. */
4972 /* todo: To check why we under miracast session, rx_chk would be false */
4973 psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.mac_address);
4974 if (psta) {
4975 if (chk_ap_is_alive(padapter, psta) == false)
4976 rx_chk = _FAIL;
4977
4978 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
4979 tx_chk = _FAIL;
4980
4981 {
4982 if (rx_chk != _SUCCESS) {
4983 if (pmlmeext->retry == 0) {
4984 issue_probereq_ex(padapter,
4985 &pmlmeinfo->network.ssid,
4986 pmlmeinfo->network.mac_address,
4987 0, 0, 0, 0);
4988 issue_probereq_ex(padapter,
4989 &pmlmeinfo->network.ssid,
4990 pmlmeinfo->network.mac_address,
4991 0, 0, 0, 0);
4992 issue_probereq_ex(padapter,
4993 &pmlmeinfo->network.ssid,
4994 pmlmeinfo->network.mac_address,
4995 0, 0, 0, 0);
4996 }
4997 }
4998
4999 if (tx_chk != _SUCCESS &&
5000 pmlmeinfo->link_count++ == link_count_limit)
5001 tx_chk = issue_nulldata_in_interrupt(padapter, NULL);
5002 }
5003
5004 if (rx_chk == _FAIL) {
5005 pmlmeext->retry++;
5006 if (pmlmeext->retry > rx_chk_limit) {
5007 netdev_dbg(padapter->pnetdev,
5008 FUNC_ADPT_FMT " disconnect or roaming\n",
5009 FUNC_ADPT_ARG(padapter));
5010 receive_disconnect(padapter, pmlmeinfo->network.mac_address
5011 , WLAN_REASON_EXPIRATION_CHK);
5012 return;
5013 }
5014 } else {
5015 pmlmeext->retry = 0;
5016 }
5017
5018 if (tx_chk == _FAIL) {
5019 pmlmeinfo->link_count %= (link_count_limit + 1);
5020 } else {
5021 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5022 pmlmeinfo->link_count = 0;
5023 }
5024
5025 } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.mac_address)) != NULL) */
5026 } else if (is_client_associated_to_ibss(padapter)) {
5027 /* linked IBSS mode */
5028 /* for each assoc list entry to check the rx pkt counter */
5029 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5030 if (pmlmeinfo->FW_sta_info[i].status == 1) {
5031 psta = pmlmeinfo->FW_sta_info[i].psta;
5032
5033 if (psta == NULL)
5034 continue;
5035
5036 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
5037 if (pmlmeinfo->FW_sta_info[i].retry < 3) {
5038 pmlmeinfo->FW_sta_info[i].retry++;
5039 } else {
5040 pmlmeinfo->FW_sta_info[i].retry = 0;
5041 pmlmeinfo->FW_sta_info[i].status = 0;
5042 report_del_sta_event(padapter, psta->hwaddr
5043 , 65535/* indicate disconnect caused by no rx */
5044 );
5045 }
5046 } else {
5047 pmlmeinfo->FW_sta_info[i].retry = 0;
5048 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5049 }
5050 }
5051 }
5052
5053 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5054 }
5055 }
5056
survey_timer_hdl(struct timer_list * t)5057 void survey_timer_hdl(struct timer_list *t)
5058 {
5059 struct adapter *padapter =
5060 timer_container_of(padapter, t, mlmeextpriv.survey_timer);
5061 struct cmd_obj *ph2c;
5062 struct sitesurvey_parm *psurveyPara;
5063 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5064 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5065
5066 /* issue rtw_sitesurvey_cmd */
5067 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5068 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
5069 pmlmeext->sitesurvey_res.channel_idx++;
5070
5071 if (pmlmeext->scan_abort) {
5072 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
5073
5074 pmlmeext->scan_abort = false;/* reset */
5075 }
5076
5077 ph2c = kzalloc_obj(*ph2c, GFP_ATOMIC);
5078 if (!ph2c)
5079 return;
5080
5081 psurveyPara = kzalloc_obj(*psurveyPara, GFP_ATOMIC);
5082 if (!psurveyPara) {
5083 kfree(ph2c);
5084 return;
5085 }
5086
5087 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
5088 rtw_enqueue_cmd(pcmdpriv, ph2c);
5089 }
5090 }
5091
link_timer_hdl(struct timer_list * t)5092 void link_timer_hdl(struct timer_list *t)
5093 {
5094 struct adapter *padapter =
5095 timer_container_of(padapter, t, mlmeextpriv.link_timer);
5096 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5097 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5098
5099
5100 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5101 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5102 report_join_res(padapter, -3);
5103 } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5104 /* re-auth timer */
5105 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5106 pmlmeinfo->state = 0;
5107 report_join_res(padapter, -1);
5108 return;
5109 }
5110
5111 pmlmeinfo->auth_seq = 1;
5112 issue_auth(padapter, NULL, 0);
5113 set_link_timer(pmlmeext, REAUTH_TO);
5114 } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5115 /* re-assoc timer */
5116 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5117 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5118 report_join_res(padapter, -2);
5119 return;
5120 }
5121
5122 issue_assocreq(padapter);
5123 set_link_timer(pmlmeext, REASSOC_TO);
5124 }
5125 }
5126
addba_timer_hdl(struct timer_list * t)5127 void addba_timer_hdl(struct timer_list *t)
5128 {
5129 struct sta_info *psta = timer_container_of(psta, t, addba_retry_timer);
5130 struct ht_priv *phtpriv;
5131
5132 if (!psta)
5133 return;
5134
5135 phtpriv = &psta->htpriv;
5136
5137 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5138 if (phtpriv->candidate_tid_bitmap)
5139 phtpriv->candidate_tid_bitmap = 0x0;
5140
5141 }
5142 }
5143
sa_query_timer_hdl(struct timer_list * t)5144 void sa_query_timer_hdl(struct timer_list *t)
5145 {
5146 struct adapter *padapter =
5147 timer_container_of(padapter, t, mlmeextpriv.sa_query_timer);
5148 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5149 /* disconnect */
5150 spin_lock_bh(&pmlmepriv->lock);
5151
5152 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
5153 rtw_disassoc_cmd(padapter, 0, true);
5154 rtw_indicate_disconnect(padapter);
5155 rtw_free_assoc_resources(padapter, 1);
5156 }
5157
5158 spin_unlock_bh(&pmlmepriv->lock);
5159 }
5160
NULL_hdl(struct adapter * padapter,u8 * pbuf)5161 u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
5162 {
5163 return H2C_SUCCESS;
5164 }
5165
setopmode_hdl(struct adapter * padapter,u8 * pbuf)5166 u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
5167 {
5168 u8 type;
5169 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5170 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5171 struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5172
5173 if (psetop->mode == Ndis802_11APMode) {
5174 pmlmeinfo->state = WIFI_FW_AP_STATE;
5175 type = _HW_STATE_AP_;
5176 /* start_ap_mode(padapter); */
5177 } else if (psetop->mode == Ndis802_11Infrastructure) {
5178 pmlmeinfo->state &= ~(BIT(0) | BIT(1));/* clear state */
5179 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
5180 type = _HW_STATE_STATION_;
5181 } else if (psetop->mode == Ndis802_11IBSS) {
5182 type = _HW_STATE_ADHOC_;
5183 } else {
5184 type = _HW_STATE_NOLINK_;
5185 }
5186
5187 rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
5188 /* set_msr(padapter, type); */
5189
5190 if (psetop->mode == Ndis802_11APMode) {
5191 /* Do this after port switch to */
5192 /* prevent from downloading rsvd page to wrong port */
5193 rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */
5194 }
5195
5196 return H2C_SUCCESS;
5197 }
5198
createbss_hdl(struct adapter * padapter,u8 * pbuf)5199 u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
5200 {
5201 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5202 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5203 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5204 struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
5205 /* u32 initialgain; */
5206
5207 if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
5208 start_bss_network(padapter);
5209 return H2C_SUCCESS;
5210 }
5211
5212 /* below is for ad-hoc master */
5213 if (pparm->network.infrastructure_mode == Ndis802_11IBSS) {
5214 rtw_joinbss_reset(padapter);
5215
5216 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5217 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5218 pmlmeinfo->ERP_enable = 0;
5219 pmlmeinfo->WMM_enable = 0;
5220 pmlmeinfo->HT_enable = 0;
5221 pmlmeinfo->HT_caps_enable = 0;
5222 pmlmeinfo->HT_info_enable = 0;
5223 pmlmeinfo->agg_enable_bitmap = 0;
5224 pmlmeinfo->candidate_tid_bitmap = 0;
5225
5226 /* disable dynamic functions, such as high power, DIG */
5227 Save_DM_Func_Flag(padapter);
5228 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5229
5230 /* config the initial gain under linking, need to write the BB registers */
5231 /* initialgain = 0x1E; */
5232 /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
5233
5234 /* cancel link timer */
5235 timer_delete_sync(&pmlmeext->link_timer);
5236
5237 /* clear CAM */
5238 flush_all_cam_entry(padapter);
5239
5240 memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length));
5241 pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
5242
5243 if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
5244 return H2C_PARAMETERS_ERROR;
5245
5246 memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
5247
5248 start_create_ibss(padapter);
5249
5250 }
5251
5252 return H2C_SUCCESS;
5253
5254 }
5255
join_cmd_hdl(struct adapter * padapter,u8 * pbuf)5256 u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5257 {
5258 u8 join_type;
5259 struct ndis_80211_var_ie *pIE;
5260 struct registry_priv *pregpriv = &padapter->registrypriv;
5261 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5262 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5263 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5264 u32 i;
5265 u8 cbw40_enable = 0;
5266 /* u32 initialgain; */
5267 /* u32 acparm; */
5268 u8 ch, bw, offset;
5269
5270 /* check already connecting to AP or not */
5271 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5272 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
5273 issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
5274 pmlmeinfo->state = WIFI_FW_NULL_STATE;
5275
5276 /* clear CAM */
5277 flush_all_cam_entry(padapter);
5278
5279 timer_delete_sync(&pmlmeext->link_timer);
5280
5281 /* set MSR to nolink -> infra. mode */
5282 /* set_msr(padapter, _HW_STATE_NOLINK_); */
5283 set_msr(padapter, _HW_STATE_STATION_);
5284
5285
5286 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
5287 }
5288
5289 rtw_joinbss_reset(padapter);
5290
5291 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5292 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5293 pmlmeinfo->ERP_enable = 0;
5294 pmlmeinfo->WMM_enable = 0;
5295 pmlmeinfo->HT_enable = 0;
5296 pmlmeinfo->HT_caps_enable = 0;
5297 pmlmeinfo->HT_info_enable = 0;
5298 pmlmeinfo->agg_enable_bitmap = 0;
5299 pmlmeinfo->candidate_tid_bitmap = 0;
5300 pmlmeinfo->bwmode_updated = false;
5301 /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
5302 pmlmeinfo->VHT_enable = 0;
5303
5304 memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length));
5305 pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
5306
5307 if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
5308 return H2C_PARAMETERS_ERROR;
5309
5310 memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
5311
5312 pmlmeext->cur_channel = (u8)pnetwork->configuration.ds_config;
5313 pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
5314
5315 /* Check AP vendor to move rtw_joinbss_cmd() */
5316 /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->ies, pnetwork->ie_length); */
5317
5318 /* sizeof(struct ndis_802_11_fix_ie) */
5319 for (i = _FIXED_IE_LENGTH_; i < pnetwork->ie_length;) {
5320 pIE = (struct ndis_80211_var_ie *)(pnetwork->ies + i);
5321
5322 switch (pIE->element_id) {
5323 case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
5324 if (!memcmp(pIE->data, WMM_OUI, 4))
5325 WMM_param_handler(padapter, pIE);
5326 break;
5327
5328 case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */
5329 pmlmeinfo->HT_caps_enable = 1;
5330 break;
5331
5332 case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */
5333 pmlmeinfo->HT_info_enable = 1;
5334
5335 /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
5336 {
5337 struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
5338
5339 if (pnetwork->configuration.ds_config <= 14) {
5340 if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
5341 cbw40_enable = 1;
5342 }
5343
5344 if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
5345 /* switch to the 40M Hz mode according to the AP */
5346 pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
5347 switch (pht_info->infos[0] & 0x3) {
5348 case 1:
5349 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
5350 break;
5351
5352 case 3:
5353 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
5354 break;
5355
5356 default:
5357 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5358 pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5359 break;
5360 }
5361 }
5362 }
5363 break;
5364 default:
5365 break;
5366 }
5367
5368 i += (pIE->length + 2);
5369 }
5370
5371 /* check channel, bandwidth, offset and switch */
5372 if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) {
5373 report_join_res(padapter, (-4));
5374 return H2C_SUCCESS;
5375 }
5376
5377 /* disable dynamic functions, such as high power, DIG */
5378 /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */
5379
5380 /* config the initial gain under linking, need to write the BB registers */
5381 /* initialgain = 0x1E; */
5382 /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
5383
5384 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.mac_address);
5385 join_type = 0;
5386 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5387 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
5388
5389 set_channel_bwmode(padapter, ch, offset, bw);
5390
5391 /* cancel link timer */
5392 timer_delete_sync(&pmlmeext->link_timer);
5393
5394 start_clnt_join(padapter);
5395
5396 return H2C_SUCCESS;
5397
5398 }
5399
disconnect_hdl(struct adapter * padapter,unsigned char * pbuf)5400 u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
5401 {
5402 struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5403 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5404 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5405 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5406 u8 val8;
5407
5408 if (is_client_associated_to_ap(padapter))
5409 issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
5410
5411 if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5412 /* Stop BCN */
5413 val8 = 0;
5414 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
5415 }
5416
5417 rtw_mlmeext_disconnect(padapter);
5418
5419 rtw_free_uc_swdec_pending_queue(padapter);
5420
5421 return H2C_SUCCESS;
5422 }
5423
rtw_scan_ch_decision(struct adapter * padapter,struct rtw_ieee80211_channel * out,u32 out_num,struct rtw_ieee80211_channel * in,u32 in_num)5424 static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
5425 u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
5426 {
5427 int i, j;
5428 int set_idx;
5429 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5430
5431 /* clear first */
5432 memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5433
5434 /* acquire channels from in */
5435 j = 0;
5436 for (i = 0; i < in_num; i++) {
5437
5438 set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
5439 if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
5440 && set_idx >= 0
5441 ) {
5442 if (j >= out_num) {
5443 netdev_dbg(padapter->pnetdev,
5444 FUNC_ADPT_FMT " out_num:%u not enough\n",
5445 FUNC_ADPT_ARG(padapter), out_num);
5446 break;
5447 }
5448
5449 memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
5450
5451 if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
5452 out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5453
5454 j++;
5455 }
5456 if (j >= out_num)
5457 break;
5458 }
5459
5460 /* if out is empty, use channel_set as default */
5461 if (j == 0) {
5462 for (i = 0; i < pmlmeext->max_chan_nums; i++) {
5463
5464 if (j >= out_num) {
5465 netdev_dbg(padapter->pnetdev,
5466 FUNC_ADPT_FMT " out_num:%u not enough\n",
5467 FUNC_ADPT_ARG(padapter),
5468 out_num);
5469 break;
5470 }
5471
5472 out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
5473
5474 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5475 out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5476
5477 j++;
5478 }
5479 }
5480
5481 return j;
5482 }
5483
sitesurvey_cmd_hdl(struct adapter * padapter,u8 * pbuf)5484 u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5485 {
5486 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5487 struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
5488 u8 bdelayscan = false;
5489 u8 val8;
5490 u32 initialgain;
5491 u32 i;
5492
5493 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5494 pmlmeext->sitesurvey_res.state = SCAN_START;
5495 pmlmeext->sitesurvey_res.bss_cnt = 0;
5496 pmlmeext->sitesurvey_res.channel_idx = 0;
5497
5498 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5499 if (pparm->ssid[i].ssid_length) {
5500 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
5501 pparm->ssid[i].ssid,
5502 IW_ESSID_MAX_SIZE);
5503 pmlmeext->sitesurvey_res.ssid[i].ssid_length =
5504 pparm->ssid[i].ssid_length;
5505 } else {
5506 pmlmeext->sitesurvey_res.ssid[i].ssid_length = 0;
5507 }
5508 }
5509
5510 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
5511 , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
5512 , pparm->ch, pparm->ch_num
5513 );
5514
5515 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5516
5517 /* issue null data if associating to the AP */
5518 if (is_client_associated_to_ap(padapter)) {
5519 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5520
5521 issue_nulldata(padapter, NULL, 1, 3, 500);
5522
5523 bdelayscan = true;
5524 }
5525 if (bdelayscan) {
5526 /* delay 50ms to protect nulldata(1). */
5527 set_survey_timer(pmlmeext, 50);
5528 return H2C_SUCCESS;
5529 }
5530 }
5531
5532 if ((pmlmeext->sitesurvey_res.state == SCAN_START) ||
5533 (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
5534 /* disable dynamic functions, such as high power, DIG */
5535 Save_DM_Func_Flag(padapter);
5536 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5537
5538 /* config the initial gain under scanning, need to write the BB
5539 * registers
5540 */
5541 initialgain = 0x1e;
5542
5543 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
5544
5545 /* set MSR to no link state */
5546 set_msr(padapter, _HW_STATE_NOLINK_);
5547
5548 val8 = 1; /* under site survey */
5549 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
5550
5551 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5552 }
5553
5554 site_survey(padapter);
5555
5556 return H2C_SUCCESS;
5557 }
5558
setauth_hdl(struct adapter * padapter,unsigned char * pbuf)5559 u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
5560 {
5561 struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
5562 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5563 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5564
5565 if (pparm->mode < 4)
5566 pmlmeinfo->auth_algo = pparm->mode;
5567
5568 return H2C_SUCCESS;
5569 }
5570
setkey_hdl(struct adapter * padapter,u8 * pbuf)5571 u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
5572 {
5573 u16 ctrl = 0;
5574 s16 cam_id = 0;
5575 struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
5576 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5577 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5578 unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5579 u8 *addr;
5580
5581 /* main tx key for wep. */
5582 if (pparm->set_tx)
5583 pmlmeinfo->key_index = pparm->keyid;
5584
5585 cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid);
5586
5587 if (cam_id < 0) {
5588 } else {
5589 if (cam_id > 3) /* not default key, searched by A2 */
5590 addr = get_bssid(&padapter->mlmepriv);
5591 else
5592 addr = null_addr;
5593
5594 ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid;
5595 write_cam(padapter, cam_id, ctrl, addr, pparm->key);
5596 netdev_dbg(padapter->pnetdev,
5597 "set group key camid:%d, addr:%pM, kid:%d, type:%s\n",
5598 cam_id, addr, pparm->keyid,
5599 security_type_str(pparm->algorithm));
5600 }
5601
5602 if (cam_id >= 0 && cam_id <= 3)
5603 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true);
5604
5605 /* allow multicast packets to driver */
5606 SetHwReg8723BS(padapter, HW_VAR_ON_RCR_AM, null_addr);
5607
5608 return H2C_SUCCESS;
5609 }
5610
set_stakey_hdl(struct adapter * padapter,u8 * pbuf)5611 u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
5612 {
5613 u16 ctrl = 0;
5614 s16 cam_id = 0;
5615 u8 ret = H2C_SUCCESS;
5616 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5617 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5618 struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
5619 struct sta_priv *pstapriv = &padapter->stapriv;
5620 struct sta_info *psta;
5621
5622 if (pparm->algorithm == _NO_PRIVACY_)
5623 goto write_to_cam;
5624
5625 psta = rtw_get_stainfo(pstapriv, pparm->addr);
5626 if (!psta) {
5627 netdev_dbg(padapter->pnetdev, "%s sta:%pM not found\n",
5628 __func__, pparm->addr);
5629 ret = H2C_REJECTED;
5630 goto exit;
5631 }
5632
5633 pmlmeinfo->enc_algo = pparm->algorithm;
5634 cam_id = rtw_camid_alloc(padapter, psta, 0);
5635 if (cam_id < 0)
5636 goto exit;
5637
5638 write_to_cam:
5639 if (pparm->algorithm == _NO_PRIVACY_) {
5640 while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) {
5641 netdev_dbg(padapter->pnetdev,
5642 "clear key for addr:%pM, camid:%d\n",
5643 pparm->addr, cam_id);
5644 clear_cam_entry(padapter, cam_id);
5645 rtw_camid_free(padapter, cam_id);
5646 }
5647 } else {
5648 netdev_dbg(padapter->pnetdev,
5649 "set pairwise key camid:%d, addr:%pM, kid:%d, type:%s\n",
5650 cam_id, pparm->addr, pparm->keyid,
5651 security_type_str(pparm->algorithm));
5652 ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
5653 write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5654 }
5655 ret = H2C_SUCCESS_RSP;
5656
5657 exit:
5658 return ret;
5659 }
5660
add_ba_hdl(struct adapter * padapter,unsigned char * pbuf)5661 u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
5662 {
5663 struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
5664 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5665 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5666
5667 struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
5668
5669 if (!psta)
5670 return H2C_SUCCESS;
5671
5672 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
5673 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5674 /* pmlmeinfo->ADDBA_retry_count = 0; */
5675 /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */
5676 /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */
5677 issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5678 /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */
5679 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
5680 } else {
5681 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
5682 }
5683 return H2C_SUCCESS;
5684 }
5685
chk_bmc_sleepq_cmd(struct adapter * padapter)5686 u8 chk_bmc_sleepq_cmd(struct adapter *padapter)
5687 {
5688 struct cmd_obj *ph2c;
5689 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
5690 u8 res = _SUCCESS;
5691
5692 ph2c = kzalloc_obj(*ph2c, GFP_ATOMIC);
5693 if (!ph2c) {
5694 res = _FAIL;
5695 goto exit;
5696 }
5697
5698 init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
5699
5700 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5701
5702 exit:
5703 return res;
5704 }
5705
set_tx_beacon_cmd(struct adapter * padapter)5706 u8 set_tx_beacon_cmd(struct adapter *padapter)
5707 {
5708 struct cmd_obj *ph2c;
5709 struct Tx_Beacon_param *ptxBeacon_parm;
5710 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
5711 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5712 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5713 u8 res = _SUCCESS;
5714 int len_diff = 0;
5715
5716 ph2c = kzalloc_obj(*ph2c, GFP_ATOMIC);
5717 if (!ph2c) {
5718 res = _FAIL;
5719 goto exit;
5720 }
5721
5722 ptxBeacon_parm = kzalloc_obj(*ptxBeacon_parm, GFP_ATOMIC);
5723 if (!ptxBeacon_parm) {
5724 kfree(ph2c);
5725 res = _FAIL;
5726 goto exit;
5727 }
5728
5729 memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
5730
5731 len_diff = update_hidden_ssid(ptxBeacon_parm->network.ies + _BEACON_IE_OFFSET_,
5732 ptxBeacon_parm->network.ie_length - _BEACON_IE_OFFSET_,
5733 pmlmeinfo->hidden_ssid_mode);
5734 ptxBeacon_parm->network.ie_length += len_diff;
5735
5736 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
5737
5738 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5739
5740 exit:
5741 return res;
5742 }
5743
5744 static struct fwevent wlanevents[] = {
5745 {0, rtw_dummy_event_callback}, /*0*/
5746 {0, NULL},
5747 {0, NULL},
5748 {0, NULL},
5749 {0, NULL},
5750 {0, NULL},
5751 {0, NULL},
5752 {0, NULL},
5753 {0, &rtw_survey_event_callback}, /*8*/
5754 {sizeof(struct surveydone_event), &rtw_surveydone_event_callback}, /*9*/
5755
5756 {0, &rtw_joinbss_event_callback}, /*10*/
5757 {sizeof(struct stassoc_event), &rtw_stassoc_event_callback},
5758 {sizeof(struct stadel_event), &rtw_stadel_event_callback},
5759 {0, &rtw_atimdone_event_callback},
5760 {0, rtw_dummy_event_callback},
5761 {0, NULL}, /*15*/
5762 {0, NULL},
5763 {0, NULL},
5764 {0, NULL},
5765 {0, rtw_fwdbg_event_callback},
5766 {0, NULL}, /*20*/
5767 {0, NULL},
5768 {0, NULL},
5769 {0, &rtw_cpwm_event_callback},
5770 {0, NULL},
5771 {0, &rtw_wmm_event_callback},
5772
5773 };
5774
mlme_evt_hdl(struct adapter * padapter,unsigned char * pbuf)5775 u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
5776 {
5777 u8 evt_code;
5778 u16 evt_sz;
5779 uint *peventbuf;
5780 void (*event_callback)(struct adapter *dev, u8 *pbuf);
5781 struct evt_priv *pevt_priv = &(padapter->evtpriv);
5782
5783 if (!pbuf)
5784 goto _abort_event_;
5785
5786 peventbuf = (uint *)pbuf;
5787 evt_sz = (u16)(*peventbuf & 0xffff);
5788 evt_code = (u8)((*peventbuf >> 16) & 0xff);
5789
5790 /* checking if event code is valid */
5791 if (evt_code >= MAX_C2HEVT)
5792 goto _abort_event_;
5793
5794 /* checking if event size match the event parm size */
5795 if ((wlanevents[evt_code].parmsize != 0) &&
5796 (wlanevents[evt_code].parmsize != evt_sz))
5797 goto _abort_event_;
5798
5799 atomic_inc(&pevt_priv->event_seq);
5800
5801 peventbuf += 2;
5802
5803 if (peventbuf) {
5804 event_callback = wlanevents[evt_code].event_callback;
5805 event_callback(padapter, (u8 *)peventbuf);
5806
5807 pevt_priv->evt_done_cnt++;
5808 }
5809
5810 _abort_event_:
5811 return H2C_SUCCESS;
5812 }
5813
h2c_msg_hdl(struct adapter * padapter,unsigned char * pbuf)5814 u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
5815 {
5816 if (!pbuf)
5817 return H2C_PARAMETERS_ERROR;
5818
5819 return H2C_SUCCESS;
5820 }
5821
chk_bmc_sleepq_hdl(struct adapter * padapter,unsigned char * pbuf)5822 u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
5823 {
5824 struct sta_info *psta_bmc;
5825 struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
5826 struct xmit_frame *pxmitframe = NULL;
5827 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5828 struct sta_priv *pstapriv = &padapter->stapriv;
5829
5830 /* for BC/MC Frames */
5831 psta_bmc = rtw_get_bcmc_stainfo(padapter);
5832 if (!psta_bmc)
5833 return H2C_SUCCESS;
5834
5835 if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) {
5836 msleep(10);/* 10ms, ATIM(HIQ) Windows */
5837
5838 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
5839 spin_lock_bh(&pxmitpriv->lock);
5840
5841 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
5842 list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
5843 pxmitframe = list_entry(xmitframe_plist,
5844 struct xmit_frame, list);
5845
5846 list_del_init(&pxmitframe->list);
5847
5848 psta_bmc->sleepq_len--;
5849 if (psta_bmc->sleepq_len > 0)
5850 pxmitframe->attrib.mdata = 1;
5851 else
5852 pxmitframe->attrib.mdata = 0;
5853
5854 pxmitframe->attrib.triggered = 1;
5855
5856 if (xmitframe_hiq_filter(pxmitframe))
5857 pxmitframe->attrib.qsel = 0x11;/* HIQ */
5858
5859 rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
5860 }
5861
5862 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
5863 spin_unlock_bh(&pxmitpriv->lock);
5864
5865 /* check hi queue and bmc_sleepq */
5866 rtw_chk_hi_queue_cmd(padapter);
5867 }
5868
5869 return H2C_SUCCESS;
5870 }
5871
tx_beacon_hdl(struct adapter * padapter,unsigned char * pbuf)5872 u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
5873 {
5874 if (send_beacon(padapter) == _FAIL)
5875 return H2C_PARAMETERS_ERROR;
5876
5877 /* tx bc/mc frames after update TIM */
5878 chk_bmc_sleepq_hdl(padapter, NULL);
5879
5880 return H2C_SUCCESS;
5881 }
5882
rtw_chk_start_clnt_join(struct adapter * padapter,u8 * ch,u8 * bw,u8 * offset)5883 int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
5884 {
5885 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5886 unsigned char cur_ch = pmlmeext->cur_channel;
5887 unsigned char cur_bw = pmlmeext->cur_bwmode;
5888 unsigned char cur_ch_offset = pmlmeext->cur_ch_offset;
5889 bool connect_allow = true;
5890
5891 if (!ch || !bw || !offset) {
5892 rtw_warn_on(1);
5893 connect_allow = false;
5894 }
5895
5896 if (connect_allow) {
5897 *ch = cur_ch;
5898 *bw = cur_bw;
5899 *offset = cur_ch_offset;
5900 }
5901
5902 return connect_allow ? _SUCCESS : _FAIL;
5903 }
5904
set_ch_hdl(struct adapter * padapter,u8 * pbuf)5905 u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
5906 {
5907 struct set_ch_parm *set_ch_parm;
5908 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5909
5910 if (!pbuf)
5911 return H2C_PARAMETERS_ERROR;
5912
5913 set_ch_parm = (struct set_ch_parm *)pbuf;
5914
5915 pmlmeext->cur_channel = set_ch_parm->ch;
5916 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
5917 pmlmeext->cur_bwmode = set_ch_parm->bw;
5918
5919 set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
5920
5921 return H2C_SUCCESS;
5922 }
5923
set_chplan_hdl(struct adapter * padapter,unsigned char * pbuf)5924 u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
5925 {
5926 struct SetChannelPlan_param *setChannelPlan_param;
5927 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5928
5929 if (!pbuf)
5930 return H2C_PARAMETERS_ERROR;
5931
5932 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
5933
5934 pmlmeext->max_chan_nums = init_channel_set(padapter,
5935 setChannelPlan_param->channel_plan,
5936 pmlmeext->channel_set);
5937 init_channel_list(padapter,
5938 pmlmeext->channel_set,
5939 pmlmeext->max_chan_nums,
5940 &pmlmeext->channel_list);
5941
5942 if (padapter->rtw_wdev && padapter->rtw_wdev->wiphy) {
5943 struct regulatory_request request;
5944
5945 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
5946 rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request);
5947 }
5948
5949 return H2C_SUCCESS;
5950 }
5951
set_csa_hdl(struct adapter * padapter,unsigned char * pbuf)5952 u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
5953 {
5954 return H2C_REJECTED;
5955 }
5956
5957 /* TDLS_ESTABLISHED : write RCR DATA BIT */
5958 /* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */
5959 /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */
5960 /* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */
5961 /* TDLS_OFF_CH : first time set channel to off channel */
5962 /* TDLS_BASE_CH : go back tp the channel linked with AP when set */
5963 /* base channel as target channel */
5964 /* TDLS_P_OFF_CH : periodically go to off channel */
5965 /* TDLS_P_BASE_CH : periodically go back to base channel */
5966 /* TDLS_RS_RCR : restore RCR */
5967 /* TDLS_TEAR_STA : free tdls sta */
tdls_hdl(struct adapter * padapter,unsigned char * pbuf)5968 u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
5969 {
5970 return H2C_REJECTED;
5971 }
5972
run_in_thread_hdl(struct adapter * padapter,u8 * pbuf)5973 u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf)
5974 {
5975 struct RunInThread_param *p;
5976
5977 if (!pbuf)
5978 return H2C_PARAMETERS_ERROR;
5979 p = (struct RunInThread_param *)pbuf;
5980
5981 if (p->func)
5982 p->func(p->context);
5983
5984 return H2C_SUCCESS;
5985 }
5986