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