1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3
4 #define _RTW_MLME_EXT_C_
5
6 #include <linux/ieee80211.h>
7 #include "../include/osdep_service.h"
8 #include "../include/drv_types.h"
9 #include "../include/wifi.h"
10 #include "../include/rtw_mlme_ext.h"
11 #include "../include/wlan_bssdef.h"
12 #include "../include/rtl8188e_xmit.h"
13 #include "../include/rtl8188e_dm.h"
14
15 /* response function for each management frame subtype, do not reorder */
16 static mlme_handler mlme_sta_tbl[] = {
17 OnAssocReq,
18 OnAssocRsp,
19 OnAssocReq,
20 OnAssocRsp,
21 OnProbeReq,
22 OnProbeRsp,
23 NULL,
24 NULL,
25 OnBeacon,
26 NULL,
27 OnDisassoc,
28 OnAuthClient,
29 OnDeAuth,
30 OnAction,
31 };
32
33 static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
34
35 /**************************************************
36 OUI definitions for the vendor specific IE
37 ***************************************************/
38 unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
39 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
40 unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
41 unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
42 unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
43
44 unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
45 unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
46
47 unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
48 unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
49
50 extern unsigned char REALTEK_96B_IE[];
51
52 /********************************************************
53 MCS rate definitions
54 *********************************************************/
55 unsigned char MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
56
57 /********************************************************
58 ChannelPlan definitions
59 *********************************************************/
60 static struct rt_channel_plan RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
61 {{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 */
62 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
63 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
64 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
65 {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
66 {{}, 0}, /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
67 };
68
69 static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
70 /* 0x00 ~ 0x1F , Old Define ===== */
71 {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
72 {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
73 {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
74 {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
75 {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
76 {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
77 {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
78 {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
79 {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
80 {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
81 {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
82 {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
83 {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
84 {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
85 {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
86 {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
87 {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
88 {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
89 {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
90 {0x00}, /* 0x13 */
91 {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
92 {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
93 {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
94 {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
95 {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
96 {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
97 {0x00}, /* 0x1A, */
98 {0x00}, /* 0x1B, */
99 {0x00}, /* 0x1C, */
100 {0x00}, /* 0x1D, */
101 {0x00}, /* 0x1E, */
102 {0x00}, /* 0x1F, */
103 /* 0x20 ~ 0x7F , New Define ===== */
104 {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
105 {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
106 {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
107 {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
108 {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
109 {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
110 {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
111 {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
112 {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
113 {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
114 {0x00}, /* 0x2A, */
115 {0x00}, /* 0x2B, */
116 {0x00}, /* 0x2C, */
117 {0x00}, /* 0x2D, */
118 {0x00}, /* 0x2E, */
119 {0x00}, /* 0x2F, */
120 {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
121 {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
122 {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
123 {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
124 {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
125 {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
126 {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
127 {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
128 {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
129 {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
130 {0x00}, /* 0x3A, */
131 {0x00}, /* 0x3B, */
132 {0x00}, /* 0x3C, */
133 {0x00}, /* 0x3D, */
134 {0x00}, /* 0x3E, */
135 {0x00}, /* 0x3F, */
136 {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
137 {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
138 };
139
140 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the conbination for max channel numbers */
141
142 /*
143 * Search the @param channel_num in given @param channel_set
144 * @ch_set: the given channel set
145 * @ch: the given channel number
146 *
147 * return the index of channel_num in channel_set, -1 if not found
148 */
rtw_ch_set_search_ch(struct rt_channel_info * ch_set,const u32 ch)149 int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
150 {
151 int i;
152 for (i = 0; ch_set[i].ChannelNum != 0; i++) {
153 if (ch == ch_set[i].ChannelNum)
154 break;
155 }
156
157 if (i >= ch_set[i].ChannelNum)
158 return -1;
159 return i;
160 }
161
162 /****************************************************************************
163
164 Following are the initialization functions for WiFi MLME
165
166 *****************************************************************************/
167
init_hw_mlme_ext(struct adapter * padapter)168 int init_hw_mlme_ext(struct adapter *padapter)
169 {
170 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
171
172 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
173 return _SUCCESS;
174 }
175
init_mlme_ext_priv_value(struct adapter * padapter)176 static void init_mlme_ext_priv_value(struct adapter *padapter)
177 {
178 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
179 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
180 unsigned char mixed_datarate[NumRates] = {
181 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
182 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
183 _48M_RATE_, _54M_RATE_, 0xff
184 };
185 unsigned char mixed_basicrate[NumRates] = {
186 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
187 _12M_RATE_, _24M_RATE_, 0xff,
188 };
189
190 atomic_set(&pmlmeext->event_seq, 0);
191 pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
192
193 pmlmeext->cur_channel = padapter->registrypriv.channel;
194 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
195 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
196 pmlmeext->retry = 0;
197
198 pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
199
200 memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
201 memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
202
203 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
204
205 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
206 pmlmeext->sitesurvey_res.channel_idx = 0;
207 pmlmeext->sitesurvey_res.bss_cnt = 0;
208 pmlmeext->scan_abort = false;
209
210 pmlmeinfo->state = WIFI_FW_NULL_STATE;
211 pmlmeinfo->reauth_count = 0;
212 pmlmeinfo->reassoc_count = 0;
213 pmlmeinfo->link_count = 0;
214 pmlmeinfo->auth_seq = 0;
215 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
216 pmlmeinfo->key_index = 0;
217 pmlmeinfo->iv = 0;
218
219 pmlmeinfo->enc_algo = _NO_PRIVACY_;
220 pmlmeinfo->authModeToggle = 0;
221
222 memset(pmlmeinfo->chg_txt, 0, 128);
223
224 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
225 pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
226
227 pmlmeinfo->dialogToken = 0;
228
229 pmlmeext->action_public_rxseq = 0xffff;
230 pmlmeext->action_public_dialog_token = 0xff;
231 }
232
has_channel(struct rt_channel_info * channel_set,u8 chanset_size,u8 chan)233 static int has_channel(struct rt_channel_info *channel_set,
234 u8 chanset_size,
235 u8 chan)
236 {
237 int i;
238
239 for (i = 0; i < chanset_size; i++) {
240 if (channel_set[i].ChannelNum == chan)
241 return 1;
242 }
243 return 0;
244 }
245
init_channel_list(struct adapter * padapter,struct rt_channel_info * channel_set,u8 chanset_size,struct p2p_channels * channel_list)246 static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
247 u8 chanset_size,
248 struct p2p_channels *channel_list)
249 {
250 struct p2p_oper_class_map op_class[] = {
251 { IEEE80211G, 81, 1, 13, 1, BW20 },
252 { IEEE80211G, 82, 14, 14, 1, BW20 },
253 { -1, 0, 0, 0, 0, BW20 }
254 };
255
256 int cla, op;
257
258 cla = 0;
259
260 for (op = 0; op_class[op].op_class; op++) {
261 u8 ch;
262 struct p2p_oper_class_map *o = &op_class[op];
263 struct p2p_reg_class *reg = NULL;
264
265 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
266 if (!has_channel(channel_set, chanset_size, ch)) {
267 continue;
268 }
269
270 if ((padapter->registrypriv.ht_enable == 0) && (o->inc == 8))
271 continue;
272
273 if (((padapter->registrypriv.cbw40_enable & BIT(1)) == 0) &&
274 ((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))
275 continue;
276
277 if (!reg) {
278 reg = &channel_list->reg_class[cla];
279 cla++;
280 reg->reg_class = o->op_class;
281 reg->channels = 0;
282 }
283 reg->channel[reg->channels] = ch;
284 reg->channels++;
285 }
286 }
287 channel_list->reg_classes = cla;
288 }
289
init_channel_set(struct adapter * padapter,u8 ChannelPlan,struct rt_channel_info * channel_set)290 static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
291 {
292 u8 index, chanset_size = 0;
293 u8 b2_4GBand = false;
294 u8 Index2G = 0;
295
296 memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
297
298 if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
299 return chanset_size;
300
301 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
302 b2_4GBand = true;
303 if (ChannelPlan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
304 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
305 else
306 Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
307 }
308
309 if (b2_4GBand) {
310 for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
311 channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
312
313 if ((ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN) ||/* Channel 1~11 is active, and 12~14 is passive */
314 (ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G)) {
315 if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
316 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
317 else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14))
318 channel_set[chanset_size].ScanType = SCAN_PASSIVE;
319 } else if (ChannelPlan == RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ||
320 Index2G == RT_CHANNEL_DOMAIN_2G_WORLD) {/* channel 12~13, passive scan */
321 if (channel_set[chanset_size].ChannelNum <= 11)
322 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
323 else
324 channel_set[chanset_size].ScanType = SCAN_PASSIVE;
325 } else {
326 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
327 }
328
329 chanset_size++;
330 }
331 }
332 return chanset_size;
333 }
334
_survey_timer_hdl(struct timer_list * t)335 static void _survey_timer_hdl(struct timer_list *t)
336 {
337 struct adapter *padapter = from_timer(padapter, t, mlmeextpriv.survey_timer);
338
339 survey_timer_hdl(padapter);
340 }
341
_link_timer_hdl(struct timer_list * t)342 static void _link_timer_hdl(struct timer_list *t)
343 {
344 struct adapter *padapter = from_timer(padapter, t, mlmeextpriv.link_timer);
345
346 link_timer_hdl(padapter);
347 }
348
init_mlme_ext_timer(struct adapter * padapter)349 static void init_mlme_ext_timer(struct adapter *padapter)
350 {
351 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
352
353 timer_setup(&pmlmeext->survey_timer, _survey_timer_hdl, 0);
354 timer_setup(&pmlmeext->link_timer, _link_timer_hdl, 0);
355 }
356
init_mlme_ext_priv(struct adapter * padapter)357 void init_mlme_ext_priv(struct adapter *padapter)
358 {
359 struct registry_priv *pregistrypriv = &padapter->registrypriv;
360 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
361 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
362 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
363
364 pmlmeext->padapter = padapter;
365
366 init_mlme_ext_priv_value(padapter);
367 pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
368
369 init_mlme_ext_timer(padapter);
370
371 init_mlme_ap_info(padapter);
372
373 pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
374 init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
375
376 pmlmeext->chan_scan_time = SURVEY_TO;
377 pmlmeext->mlmeext_init = true;
378
379 pmlmeext->active_keep_alive_check = true;
380 }
381
free_mlme_ext_priv(struct mlme_ext_priv * pmlmeext)382 void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
383 {
384 struct adapter *padapter = pmlmeext->padapter;
385
386 if (!padapter)
387 return;
388
389 if (padapter->bDriverStopped) {
390 _cancel_timer_ex(&pmlmeext->survey_timer);
391 _cancel_timer_ex(&pmlmeext->link_timer);
392 /* _cancel_timer_ex(&pmlmeext->ADDBA_timer); */
393 }
394 }
395
mgt_dispatcher(struct adapter * padapter,struct recv_frame * precv_frame)396 void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame)
397 {
398 int index;
399 mlme_handler fct;
400 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
401 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)precv_frame->rx_data;
402 struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, hdr->addr2);
403
404 if (!ieee80211_is_mgmt(hdr->frame_control))
405 return;
406
407 /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
408 if (memcmp(hdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN) &&
409 !is_broadcast_ether_addr(hdr->addr1))
410 return;
411
412 index = (le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
413 if (index >= ARRAY_SIZE(mlme_sta_tbl))
414 return;
415 fct = mlme_sta_tbl[index];
416
417 if (psta) {
418 if (ieee80211_has_retry(hdr->frame_control)) {
419 if (precv_frame->attrib.seq_num == psta->RxMgmtFrameSeqNum)
420 /* drop the duplicate management frame */
421 return;
422 }
423 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
424 }
425
426 if (ieee80211_is_auth(hdr->frame_control)) {
427 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
428 fct = OnAuth;
429 else
430 fct = OnAuthClient;
431 }
432
433 if (fct)
434 fct(padapter, precv_frame);
435 }
436
p2p_listen_state_process(struct adapter * padapter,unsigned char * da)437 static u32 p2p_listen_state_process(struct adapter *padapter, unsigned char *da)
438 {
439 bool response = true;
440
441 /* do nothing if the device name is empty */
442 if (!padapter->wdinfo.device_name_len)
443 response = false;
444
445 if (response)
446 issue_probersp_p2p(padapter, da);
447
448 return _SUCCESS;
449 }
450
update_TSF(struct mlme_ext_priv * pmlmeext,u8 * pframe)451 static void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe)
452 {
453 u8 *pIE;
454 __le32 *pbuf;
455
456 pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
457 pbuf = (__le32 *)pIE;
458
459 pmlmeext->TSFValue = le32_to_cpu(*(pbuf + 1));
460
461 pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
462
463 pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
464 }
465
correct_TSF(struct adapter * padapter)466 static void correct_TSF(struct adapter *padapter)
467 {
468 u8 reg;
469 int res;
470 u64 tsf;
471 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
472 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
473
474 tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue,
475 pmlmeinfo->bcn_interval * 1024) - 1024; /* us */
476
477 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
478 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
479 rtw_stop_tx_beacon(padapter);
480
481 /* disable related TSF function */
482 res = rtw_read8(padapter, REG_BCN_CTRL, ®);
483 if (res)
484 return;
485
486 rtw_write8(padapter, REG_BCN_CTRL, reg & (~BIT(3)));
487
488 rtw_write32(padapter, REG_TSFTR, tsf);
489 rtw_write32(padapter, REG_TSFTR + 4, tsf >> 32);
490
491 /* enable related TSF function */
492 res = rtw_read8(padapter, REG_BCN_CTRL, ®);
493 if (res)
494 return;
495
496 rtw_write8(padapter, REG_BCN_CTRL, reg | BIT(3));
497
498 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
499 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
500 rtw_resume_tx_beacon(padapter);
501 }
502
503 /****************************************************************************
504
505 Following are the callback functions for each subtype of the management frames
506
507 *****************************************************************************/
508
OnProbeReq(struct adapter * padapter,struct recv_frame * precv_frame)509 unsigned int OnProbeReq(struct adapter *padapter, struct recv_frame *precv_frame)
510 {
511 unsigned int ielen;
512 unsigned char *p;
513 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
514 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
515 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
516 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
517 u8 *pframe = precv_frame->rx_data;
518 uint len = precv_frame->len;
519 u8 is_valid_p2p_probereq = false;
520
521 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
522
523 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
524 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
525 !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
526 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
527 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
528 /* mcs_rate = 0 -> CCK 1M rate */
529 /* mcs_rate = 1 -> CCK 2M rate */
530 /* mcs_rate = 2 -> CCK 5.5M rate */
531 /* mcs_rate = 3 -> CCK 11M rate */
532 /* In the P2P mode, the driver should not support the CCK rate */
533
534 /* Commented by Kurt 2012/10/16 */
535 /* IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */
536 is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len);
537 if (is_valid_p2p_probereq) {
538 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
539 /* FIXME */
540 report_survey_event(padapter, precv_frame);
541 p2p_listen_state_process(padapter, get_sa(pframe));
542
543 return _SUCCESS;
544 }
545 }
546 }
547
548 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
549 return _SUCCESS;
550
551 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
552 !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
553 return _SUCCESS;
554
555 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
556 len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
557
558 /* check (wildcard) SSID */
559 if (p) {
560 if (is_valid_p2p_probereq)
561 goto _issue_probersp;
562
563 if ((ielen != 0 && memcmp((void *)(p + 2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
564 (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
565 return _SUCCESS;
566
567 _issue_probersp:
568
569 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
570 (pmlmepriv->cur_network.join_res ||
571 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
572 issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
573 }
574 return _SUCCESS;
575 }
576
OnProbeRsp(struct adapter * padapter,struct recv_frame * precv_frame)577 unsigned int OnProbeRsp(struct adapter *padapter, struct recv_frame *precv_frame)
578 {
579 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
580 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
581 u8 *pframe = precv_frame->rx_data;
582
583 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
584 if (pwdinfo->tx_prov_disc_info.benable) {
585 if (!memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
586 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
587 pwdinfo->tx_prov_disc_info.benable = false;
588 issue_p2p_provision_request(padapter,
589 pwdinfo->tx_prov_disc_info.ssid.Ssid,
590 pwdinfo->tx_prov_disc_info.ssid.SsidLength,
591 pwdinfo->tx_prov_disc_info.peerDevAddr);
592 } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
593 pwdinfo->tx_prov_disc_info.benable = false;
594 issue_p2p_provision_request(padapter, NULL, 0,
595 pwdinfo->tx_prov_disc_info.peerDevAddr);
596 }
597 }
598 }
599 return _SUCCESS;
600 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
601 if (pwdinfo->nego_req_info.benable) {
602 if (!memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
603 pwdinfo->nego_req_info.benable = false;
604 issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);
605 }
606 }
607 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
608 if (pwdinfo->invitereq_info.benable) {
609 if (!memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
610 pwdinfo->invitereq_info.benable = false;
611 issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);
612 }
613 }
614 }
615 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
616 report_survey_event(padapter, precv_frame);
617 return _SUCCESS;
618 }
619
620 return _SUCCESS;
621 }
622
OnBeacon(struct adapter * padapter,struct recv_frame * precv_frame)623 unsigned int OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame)
624 {
625 int cam_idx;
626 struct sta_info *psta;
627 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
628 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
629 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
630 struct sta_priv *pstapriv = &padapter->stapriv;
631 u8 *pframe = precv_frame->rx_data;
632 uint len = precv_frame->len;
633 struct wlan_bssid_ex *pbss;
634 int ret = _SUCCESS;
635
636 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
637 report_survey_event(padapter, precv_frame);
638 return _SUCCESS;
639 }
640
641 if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
642 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
643 /* we should update current network before auth, or some IE is wrong */
644 pbss = kmalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
645 if (pbss) {
646 if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
647 update_network(&pmlmepriv->cur_network.network, pbss, padapter, true);
648 rtw_get_bcn_info(&pmlmepriv->cur_network);
649 }
650 kfree(pbss);
651 }
652
653 /* check the vendor of the assoc AP */
654 pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct ieee80211_hdr_3addr), len - sizeof(struct ieee80211_hdr_3addr));
655
656 /* update TSF Value */
657 update_TSF(pmlmeext, pframe);
658
659 /* start auth */
660 start_clnt_auth(padapter);
661
662 return _SUCCESS;
663 }
664
665 if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
666 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
667 if (psta) {
668 ret = rtw_check_bcn_info(padapter, pframe, len);
669 if (!ret) {
670 receive_disconnect(padapter,
671 pmlmeinfo->network.MacAddress, 0);
672 return _SUCCESS;
673 }
674 /* update WMM, ERP in the beacon */
675 /* todo: the timer is used instead of the number of the beacon received */
676 if ((sta_rx_pkts(psta) & 0xf) == 0)
677 update_beacon_info(padapter, pframe, len, psta);
678 process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
679 }
680 } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
681 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
682 if (psta) {
683 /* update WMM, ERP in the beacon */
684 /* todo: the timer is used instead of the number of the beacon received */
685 if ((sta_rx_pkts(psta) & 0xf) == 0)
686 update_beacon_info(padapter, pframe, len, psta);
687 } else {
688 /* allocate a new CAM entry for IBSS station */
689 cam_idx = allocate_fw_sta_entry(padapter);
690 if (cam_idx == NUM_STA)
691 goto _END_ONBEACON_;
692
693 /* get supported rate */
694 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) {
695 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
696 goto _END_ONBEACON_;
697 }
698
699 /* update TSF Value */
700 update_TSF(pmlmeext, pframe);
701
702 /* report sta add event */
703 report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
704 }
705 }
706 }
707
708 _END_ONBEACON_:
709
710 return _SUCCESS;
711 }
712
OnAuth(struct adapter * padapter,struct recv_frame * precv_frame)713 unsigned int OnAuth(struct adapter *padapter, struct recv_frame *precv_frame)
714 {
715 unsigned int auth_mode, ie_len;
716 u16 seq;
717 unsigned char *sa, *p;
718 u16 algorithm;
719 int status;
720 static struct sta_info stat;
721 struct sta_info *pstat = NULL;
722 struct sta_priv *pstapriv = &padapter->stapriv;
723 struct security_priv *psecuritypriv = &padapter->securitypriv;
724 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
725 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
726 u8 *pframe = precv_frame->rx_data;
727 uint len = precv_frame->len;
728
729 if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
730 return _FAIL;
731
732 sa = GetAddr2Ptr(pframe);
733
734 auth_mode = psecuritypriv->dot11AuthAlgrthm;
735 seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
736 algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
737
738 if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
739 psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
740 auth_mode = 0;
741
742 if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */
743 (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */
744
745 status = _STATS_NO_SUPP_ALG_;
746
747 goto auth_fail;
748 }
749
750 if (!rtw_access_ctrl(padapter, sa)) {
751 status = _STATS_UNABLE_HANDLE_STA_;
752 goto auth_fail;
753 }
754
755 pstat = rtw_get_stainfo(pstapriv, sa);
756 if (!pstat) {
757 /* allocate a new one */
758 pstat = rtw_alloc_stainfo(pstapriv, sa);
759 if (!pstat) {
760 status = _STATS_UNABLE_HANDLE_STA_;
761 goto auth_fail;
762 }
763
764 pstat->state = WIFI_FW_AUTH_NULL;
765 pstat->auth_seq = 0;
766 } else {
767 spin_lock_bh(&pstapriv->asoc_list_lock);
768 if (!list_empty(&pstat->asoc_list)) {
769 list_del_init(&pstat->asoc_list);
770 pstapriv->asoc_list_cnt--;
771 }
772 spin_unlock_bh(&pstapriv->asoc_list_lock);
773
774 if (seq == 1) {
775 /* TODO: STA re_auth and auth timeout */
776 }
777 }
778
779 spin_lock_bh(&pstapriv->auth_list_lock);
780 if (list_empty(&pstat->auth_list)) {
781 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
782 pstapriv->auth_list_cnt++;
783 }
784 spin_unlock_bh(&pstapriv->auth_list_lock);
785
786 if (pstat->auth_seq == 0)
787 pstat->expire_to = pstapriv->auth_to;
788
789 if ((pstat->auth_seq + 1) != seq) {
790 status = _STATS_OUT_OF_AUTH_SEQ_;
791 goto auth_fail;
792 }
793
794 if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
795 if (seq == 1) {
796 pstat->state &= ~WIFI_FW_AUTH_NULL;
797 pstat->state |= WIFI_FW_AUTH_SUCCESS;
798 pstat->expire_to = pstapriv->assoc_to;
799 pstat->authalg = algorithm;
800 } else {
801 status = _STATS_OUT_OF_AUTH_SEQ_;
802 goto auth_fail;
803 }
804 } else { /* shared system or auto authentication */
805 if (seq == 1) {
806 /* prepare for the challenging txt... */
807
808 pstat->state &= ~WIFI_FW_AUTH_NULL;
809 pstat->state |= WIFI_FW_AUTH_STATE;
810 pstat->authalg = algorithm;
811 pstat->auth_seq = 2;
812 } else if (seq == 3) {
813 /* checking for challenging txt... */
814
815 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len,
816 len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
817
818 if (!p || ie_len <= 0) {
819 status = _STATS_CHALLENGE_FAIL_;
820 goto auth_fail;
821 }
822
823 if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
824 pstat->state &= (~WIFI_FW_AUTH_STATE);
825 pstat->state |= WIFI_FW_AUTH_SUCCESS;
826 /* challenging txt is correct... */
827 pstat->expire_to = pstapriv->assoc_to;
828 } else {
829 status = _STATS_CHALLENGE_FAIL_;
830 goto auth_fail;
831 }
832 } else {
833 status = _STATS_OUT_OF_AUTH_SEQ_;
834 goto auth_fail;
835 }
836 }
837
838 /* Now, we are going to issue_auth... */
839 pstat->auth_seq = seq + 1;
840
841 issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
842
843 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
844 pstat->auth_seq = 0;
845
846 return _SUCCESS;
847
848 auth_fail:
849
850 if (pstat)
851 rtw_free_stainfo(padapter, pstat);
852
853 pstat = &stat;
854 memset((char *)pstat, '\0', sizeof(stat));
855 pstat->auth_seq = 2;
856 memcpy(pstat->hwaddr, sa, 6);
857
858 issue_auth(padapter, pstat, (unsigned short)status);
859 return _FAIL;
860 }
861
OnAuthClient(struct adapter * padapter,struct recv_frame * precv_frame)862 unsigned int OnAuthClient(struct adapter *padapter, struct recv_frame *precv_frame)
863 {
864 unsigned int seq, len, status, offset;
865 unsigned char *p;
866 unsigned int go2asoc = 0;
867 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
868 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
869 u8 *pframe = precv_frame->rx_data;
870 uint pkt_len = precv_frame->len;
871
872 /* check A1 matches or not */
873 if (memcmp(myid(&padapter->eeprompriv), get_da(pframe), ETH_ALEN))
874 return _SUCCESS;
875
876 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
877 return _SUCCESS;
878
879 offset = (GetPrivacy(pframe)) ? 4 : 0;
880
881 seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
882 status = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
883
884 if (status != 0) {
885 if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
886 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
887 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
888 else
889 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
890 }
891
892 set_link_timer(pmlmeext, 1);
893 goto authclnt_fail;
894 }
895
896 if (seq == 2) {
897 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
898 /* legendary shared system */
899 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
900 pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
901
902 if (!p)
903 goto authclnt_fail;
904
905 memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
906 pmlmeinfo->auth_seq = 3;
907 issue_auth(padapter, NULL, 0);
908 set_link_timer(pmlmeext, REAUTH_TO);
909
910 return _SUCCESS;
911 } else {
912 /* open system */
913 go2asoc = 1;
914 }
915 } else if (seq == 4) {
916 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
917 go2asoc = 1;
918 else
919 goto authclnt_fail;
920 } else {
921 /* this is also illegal */
922 goto authclnt_fail;
923 }
924
925 if (go2asoc) {
926 start_clnt_assoc(padapter);
927 return _SUCCESS;
928 }
929 authclnt_fail:
930 return _FAIL;
931 }
932
UpdateBrateTbl(u8 * mbrate)933 static void UpdateBrateTbl(u8 *mbrate)
934 {
935 u8 i;
936 u8 rate;
937
938 /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
939 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
940 rate = mbrate[i] & 0x7f;
941 switch (rate) {
942 case IEEE80211_CCK_RATE_1MB:
943 case IEEE80211_CCK_RATE_2MB:
944 case IEEE80211_CCK_RATE_5MB:
945 case IEEE80211_CCK_RATE_11MB:
946 case IEEE80211_OFDM_RATE_6MB:
947 case IEEE80211_OFDM_RATE_12MB:
948 case IEEE80211_OFDM_RATE_24MB:
949 mbrate[i] |= IEEE80211_BASIC_RATE_MASK;
950 break;
951 }
952 }
953 }
954
UpdateBrateTblForSoftAP(u8 * bssrateset,u32 bssratelen)955 static void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
956 {
957 u8 i;
958 u8 rate;
959
960 for (i = 0; i < bssratelen; i++) {
961 rate = bssrateset[i] & 0x7f;
962 switch (rate) {
963 case IEEE80211_CCK_RATE_1MB:
964 case IEEE80211_CCK_RATE_2MB:
965 case IEEE80211_CCK_RATE_5MB:
966 case IEEE80211_CCK_RATE_11MB:
967 bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
968 break;
969 }
970 }
971 }
972
OnAssocReq(struct adapter * padapter,struct recv_frame * precv_frame)973 unsigned int OnAssocReq(struct adapter *padapter, struct recv_frame *precv_frame)
974 {
975 u16 capab_info;
976 struct rtw_ieee802_11_elems elems;
977 struct sta_info *pstat;
978 unsigned char *p, *pos, *wpa_ie;
979 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
980 int i, ie_len, wpa_ie_len, left;
981 unsigned char supportRate[16];
982 int supportRateNum;
983 unsigned short status = _STATS_SUCCESSFUL_;
984 unsigned short frame_type, ie_offset = 0;
985 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
986 struct security_priv *psecuritypriv = &padapter->securitypriv;
987 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
988 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
989 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
990 struct sta_priv *pstapriv = &padapter->stapriv;
991 u8 *pframe = precv_frame->rx_data;
992 uint pkt_len = precv_frame->len;
993 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
994 u8 p2p_status_code = P2P_STATUS_SUCCESS;
995 u8 *p2pie;
996 u32 p2pielen = 0;
997
998 if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
999 return _FAIL;
1000
1001 frame_type = GetFrameSubType(pframe);
1002 if (frame_type == WIFI_ASSOCREQ)
1003 ie_offset = _ASOCREQ_IE_OFFSET_;
1004 else /* WIFI_REASSOCREQ */
1005 ie_offset = _REASOCREQ_IE_OFFSET_;
1006
1007 if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset)
1008 return _FAIL;
1009
1010 pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1011 if (pstat == (struct sta_info *)NULL) {
1012 status = _RSON_CLS2_;
1013 goto asoc_class2_error;
1014 }
1015
1016 capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
1017
1018 left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
1019 pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
1020
1021 /* check if this stat has been successfully authenticated/assocated */
1022 if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
1023 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
1024 status = _RSON_CLS2_;
1025 goto asoc_class2_error;
1026 } else {
1027 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1028 pstat->state |= WIFI_FW_ASSOC_STATE;
1029 }
1030 } else {
1031 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1032 pstat->state |= WIFI_FW_ASSOC_STATE;
1033 }
1034 pstat->capability = capab_info;
1035 /* now parse all ieee802_11 ie to point to elems */
1036 if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1037 !elems.ssid) {
1038 status = _STATS_FAILURE_;
1039 goto OnAssocReqFail;
1040 }
1041
1042 /* now we should check all the fields... */
1043 /* checking SSID */
1044 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
1045 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1046 if (!p)
1047 status = _STATS_FAILURE_;
1048
1049 if (ie_len == 0) { /* broadcast ssid, however it is not allowed in assocreq */
1050 status = _STATS_FAILURE_;
1051 } else {
1052 /* check if ssid match */
1053 if (memcmp((void *)(p + 2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1054 status = _STATS_FAILURE_;
1055
1056 if (ie_len != cur->Ssid.SsidLength)
1057 status = _STATS_FAILURE_;
1058 }
1059
1060 if (status != _STATS_SUCCESSFUL_)
1061 goto OnAssocReqFail;
1062
1063 /* check if the supported rate is ok */
1064 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1065 if (!p) {
1066 /* use our own rate set as statoin used */
1067 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1068 /* supportRateNum = AP_BSSRATE_LEN; */
1069
1070 status = _STATS_FAILURE_;
1071 goto OnAssocReqFail;
1072 } else {
1073 memcpy(supportRate, p + 2, ie_len);
1074 supportRateNum = ie_len;
1075
1076 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
1077 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1078 if (p) {
1079 if (supportRateNum <= sizeof(supportRate)) {
1080 memcpy(supportRate + supportRateNum, p + 2, ie_len);
1081 supportRateNum += ie_len;
1082 }
1083 }
1084 }
1085
1086 /* todo: mask supportRate between AP & STA -> move to update raid */
1087 /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1088
1089 /* update station supportRate */
1090 pstat->bssratelen = supportRateNum;
1091 memcpy(pstat->bssrateset, supportRate, supportRateNum);
1092 UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1093
1094 /* check RSN/WPA/WPS */
1095 pstat->dot8021xalg = 0;
1096 pstat->wpa_psk = 0;
1097 pstat->wpa_group_cipher = 0;
1098 pstat->wpa2_group_cipher = 0;
1099 pstat->wpa_pairwise_cipher = 0;
1100 pstat->wpa2_pairwise_cipher = 0;
1101 memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1102 if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1103 int group_cipher = 0, pairwise_cipher = 0;
1104
1105 wpa_ie = elems.rsn_ie;
1106 wpa_ie_len = elems.rsn_ie_len;
1107
1108 if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1109 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1110 pstat->wpa_psk |= BIT(1);
1111
1112 pstat->wpa2_group_cipher = group_cipher & psecuritypriv->wpa2_group_cipher;
1113 pstat->wpa2_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa2_pairwise_cipher;
1114
1115 if (!pstat->wpa2_group_cipher)
1116 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1117
1118 if (!pstat->wpa2_pairwise_cipher)
1119 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1120 } else {
1121 status = WLAN_STATUS_INVALID_IE;
1122 }
1123 } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1124 int group_cipher = 0, pairwise_cipher = 0;
1125
1126 wpa_ie = elems.wpa_ie;
1127 wpa_ie_len = elems.wpa_ie_len;
1128
1129 if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1130 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1131 pstat->wpa_psk |= BIT(0);
1132
1133 pstat->wpa_group_cipher = group_cipher & psecuritypriv->wpa_group_cipher;
1134 pstat->wpa_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa_pairwise_cipher;
1135
1136 if (!pstat->wpa_group_cipher)
1137 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1138
1139 if (!pstat->wpa_pairwise_cipher)
1140 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1141 } else {
1142 status = WLAN_STATUS_INVALID_IE;
1143 }
1144 } else {
1145 wpa_ie = NULL;
1146 wpa_ie_len = 0;
1147 }
1148
1149 if (status != _STATS_SUCCESSFUL_)
1150 goto OnAssocReqFail;
1151
1152 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1153 if (!wpa_ie) {
1154 if (elems.wps_ie)
1155 pstat->flags |= WLAN_STA_WPS;
1156 /* wpabuf_free(sta->wps_ie); */
1157 /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
1158 /* elems.wps_ie_len - 4); */
1159 else
1160 pstat->flags |= WLAN_STA_MAYBE_WPS;
1161
1162 /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1163 /* that the selected registrar of AP is _FLASE */
1164 if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
1165 if (pmlmepriv->wps_beacon_ie) {
1166 u8 selected_registrar = 0;
1167
1168 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1169
1170 if (!selected_registrar) {
1171
1172 status = _STATS_UNABLE_HANDLE_STA_;
1173
1174 goto OnAssocReqFail;
1175 }
1176 }
1177 }
1178 } else {
1179 int copy_len;
1180
1181 if (psecuritypriv->wpa_psk == 0) {
1182
1183 status = WLAN_STATUS_INVALID_IE;
1184
1185 goto OnAssocReqFail;
1186 }
1187
1188 if (elems.wps_ie) {
1189 pstat->flags |= WLAN_STA_WPS;
1190 copy_len = 0;
1191 } else {
1192 copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len + 2);
1193 }
1194 if (copy_len > 0)
1195 memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
1196 }
1197 /* check if there is WMM IE & support WWM-PS */
1198 pstat->flags &= ~WLAN_STA_WME;
1199 pstat->qos_option = 0;
1200 pstat->qos_info = 0;
1201 pstat->has_legacy_ac = true;
1202 pstat->uapsd_vo = 0;
1203 pstat->uapsd_vi = 0;
1204 pstat->uapsd_be = 0;
1205 pstat->uapsd_bk = 0;
1206 if (pmlmepriv->qospriv.qos_option) {
1207 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1208 for (;;) {
1209 p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1210 if (p) {
1211 if (!memcmp(p + 2, WMM_IE, 6)) {
1212 pstat->flags |= WLAN_STA_WME;
1213
1214 pstat->qos_option = 1;
1215 pstat->qos_info = *(p + 8);
1216
1217 pstat->max_sp_len = (pstat->qos_info >> 5) & 0x3;
1218
1219 if ((pstat->qos_info & 0xf) != 0xf)
1220 pstat->has_legacy_ac = true;
1221 else
1222 pstat->has_legacy_ac = false;
1223
1224 if (pstat->qos_info & 0xf) {
1225 if (pstat->qos_info & BIT(0))
1226 pstat->uapsd_vo = BIT(0) | BIT(1);
1227 else
1228 pstat->uapsd_vo = 0;
1229
1230 if (pstat->qos_info & BIT(1))
1231 pstat->uapsd_vi = BIT(0) | BIT(1);
1232 else
1233 pstat->uapsd_vi = 0;
1234
1235 if (pstat->qos_info & BIT(2))
1236 pstat->uapsd_bk = BIT(0) | BIT(1);
1237 else
1238 pstat->uapsd_bk = 0;
1239
1240 if (pstat->qos_info & BIT(3))
1241 pstat->uapsd_be = BIT(0) | BIT(1);
1242 else
1243 pstat->uapsd_be = 0;
1244 }
1245 break;
1246 }
1247 } else {
1248 break;
1249 }
1250 p = p + ie_len + 2;
1251 }
1252 }
1253
1254 /* save HT capabilities in the sta object */
1255 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1256 if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
1257 pstat->flags |= WLAN_STA_HT;
1258
1259 pstat->flags |= WLAN_STA_WME;
1260
1261 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
1262 } else {
1263 pstat->flags &= ~WLAN_STA_HT;
1264 }
1265 if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags & WLAN_STA_HT)) {
1266 status = _STATS_FAILURE_;
1267 goto OnAssocReqFail;
1268 }
1269
1270 pstat->flags |= WLAN_STA_NONERP;
1271 for (i = 0; i < pstat->bssratelen; i++) {
1272 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1273 pstat->flags &= ~WLAN_STA_NONERP;
1274 break;
1275 }
1276 }
1277
1278 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1279 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1280 else
1281 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1282
1283 if (status != _STATS_SUCCESSFUL_)
1284 goto OnAssocReqFail;
1285
1286 pstat->is_p2p_device = false;
1287 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1288 p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset, NULL, &p2pielen);
1289 if (p2pie) {
1290 pstat->is_p2p_device = true;
1291 p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat);
1292 if (p2p_status_code > 0) {
1293 pstat->p2p_status_code = p2p_status_code;
1294 status = _STATS_CAP_FAIL_;
1295 goto OnAssocReqFail;
1296 }
1297 }
1298 }
1299 pstat->p2p_status_code = p2p_status_code;
1300
1301 /* TODO: identify_proprietary_vendor_ie(); */
1302 /* Realtek proprietary IE */
1303 /* identify if this is Broadcom sta */
1304 /* identify if this is ralink sta */
1305 /* Customer proprietary IE */
1306
1307 /* get a unique AID */
1308 if (pstat->aid == 0) {
1309 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1310 if (!pstapriv->sta_aid[pstat->aid - 1])
1311 break;
1312
1313 /* if (pstat->aid > NUM_STA) { */
1314 if (pstat->aid > pstapriv->max_num_sta) {
1315 pstat->aid = 0;
1316
1317 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1318
1319 goto OnAssocReqFail;
1320 } else {
1321 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1322 }
1323 }
1324
1325 pstat->state &= (~WIFI_FW_ASSOC_STATE);
1326 pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1327
1328 spin_lock_bh(&pstapriv->auth_list_lock);
1329 if (!list_empty(&pstat->auth_list)) {
1330 list_del_init(&pstat->auth_list);
1331 pstapriv->auth_list_cnt--;
1332 }
1333 spin_unlock_bh(&pstapriv->auth_list_lock);
1334
1335 spin_lock_bh(&pstapriv->asoc_list_lock);
1336 if (list_empty(&pstat->asoc_list)) {
1337 pstat->expire_to = pstapriv->expire_to;
1338 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1339 pstapriv->asoc_list_cnt++;
1340 }
1341 spin_unlock_bh(&pstapriv->asoc_list_lock);
1342
1343 /* now the station is qualified to join our BSS... */
1344 if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (status == _STATS_SUCCESSFUL_)) {
1345 /* 1 bss_cap_update & sta_info_update */
1346 bss_cap_update_on_sta_join(padapter, pstat);
1347 sta_info_update(padapter, pstat);
1348
1349 /* issue assoc rsp before notify station join event. */
1350 if (frame_type == WIFI_ASSOCREQ)
1351 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1352 else
1353 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1354
1355 /* 2 - report to upper layer */
1356 rtw_indicate_sta_assoc_event(padapter, pstat);
1357
1358 /* 3-(1) report sta add event */
1359 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1360 }
1361
1362 return _SUCCESS;
1363
1364 asoc_class2_error:
1365
1366 issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1367
1368 return _FAIL;
1369
1370 OnAssocReqFail:
1371
1372 pstat->aid = 0;
1373 if (frame_type == WIFI_ASSOCREQ)
1374 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1375 else
1376 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1377
1378 return _FAIL;
1379 }
1380
OnAssocRsp(struct adapter * padapter,struct recv_frame * precv_frame)1381 unsigned int OnAssocRsp(struct adapter *padapter, struct recv_frame *precv_frame)
1382 {
1383 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data;
1384 uint i;
1385 int res;
1386 struct ndis_802_11_var_ie *pIE;
1387 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1388 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1389 /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
1390 u8 *pframe = precv_frame->rx_data;
1391 uint pkt_len = precv_frame->len;
1392
1393 /* check A1 matches or not */
1394 if (memcmp(myid(&padapter->eeprompriv), mgmt->da, ETH_ALEN))
1395 return _SUCCESS;
1396
1397 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1398 return _SUCCESS;
1399
1400 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1401 return _SUCCESS;
1402
1403 _cancel_timer_ex(&pmlmeext->link_timer);
1404
1405 if (le16_to_cpu(mgmt->u.assoc_resp.status_code) > 0) {
1406 pmlmeinfo->state = WIFI_FW_NULL_STATE;
1407 res = -4;
1408 goto report_assoc_result;
1409 }
1410
1411 pmlmeinfo->capability = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
1412
1413 /* set slot time */
1414 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1415
1416 pmlmeinfo->aid = le16_to_cpu(mgmt->u.assoc_resp.aid) & 0x3fff;
1417 res = pmlmeinfo->aid;
1418
1419 /* following are moved to join event callback function */
1420 /* to handle HT, WMM, rate adaptive, update MAC reg */
1421 /* for not to handle the synchronous IO in the tasklet */
1422 for (i = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); i < pkt_len;) {
1423 pIE = (struct ndis_802_11_var_ie *)(pframe + i);
1424
1425 switch (pIE->ElementID) {
1426 case _VENDOR_SPECIFIC_IE_:
1427 if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
1428 WMM_param_handler(padapter, pIE);
1429 break;
1430 case _HT_CAPABILITY_IE_: /* HT caps */
1431 HT_caps_handler(padapter, pIE);
1432 break;
1433 case _HT_EXTRA_INFO_IE_: /* HT info */
1434 HT_info_handler(padapter, pIE);
1435 break;
1436 case _ERPINFO_IE_:
1437 ERP_IE_handler(padapter, pIE);
1438 break;
1439 default:
1440 break;
1441 }
1442
1443 i += (pIE->Length + 2);
1444 }
1445
1446 pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1447 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1448
1449 /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1450 UpdateBrateTbl(pmlmeinfo->network.SupportedRates);
1451
1452 report_assoc_result:
1453 report_join_res(padapter, res);
1454
1455 return _SUCCESS;
1456 }
1457
OnDeAuth(struct adapter * padapter,struct recv_frame * precv_frame)1458 unsigned int OnDeAuth(struct adapter *padapter, struct recv_frame *precv_frame)
1459 {
1460 unsigned short reason;
1461 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1462 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1463 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1464 u8 *pframe = precv_frame->rx_data;
1465 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1466
1467 /* check A3 */
1468 if (!(!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
1469 return _SUCCESS;
1470
1471 if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1472 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1473 _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
1474 }
1475
1476 reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1477
1478 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1479 struct sta_info *psta;
1480 struct sta_priv *pstapriv = &padapter->stapriv;
1481
1482 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1483 if (psta) {
1484 u8 updated = 0;
1485
1486 spin_lock_bh(&pstapriv->asoc_list_lock);
1487 if (!list_empty(&psta->asoc_list)) {
1488 list_del_init(&psta->asoc_list);
1489 pstapriv->asoc_list_cnt--;
1490 updated = ap_free_sta(padapter, psta, false, reason);
1491 }
1492 spin_unlock_bh(&pstapriv->asoc_list_lock);
1493
1494 associated_clients_update(padapter, updated);
1495 }
1496
1497 return _SUCCESS;
1498 } else {
1499 int ignore_received_deauth = 0;
1500
1501 /* Before sending the auth frame to start the STA/GC mode connection with AP/GO,
1502 * we will send the deauth first.
1503 * However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth.
1504 * Added the following code to avoid this case.
1505 */
1506 if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
1507 (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
1508 if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
1509 ignore_received_deauth = 1;
1510 } else if (reason == WLAN_REASON_PREV_AUTH_NOT_VALID) {
1511 // TODO: 802.11r
1512 ignore_received_deauth = 1;
1513 }
1514 }
1515
1516 if (!ignore_received_deauth)
1517 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1518 }
1519 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1520 return _SUCCESS;
1521 }
1522
OnDisassoc(struct adapter * padapter,struct recv_frame * precv_frame)1523 unsigned int OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame)
1524 {
1525 u16 reason;
1526 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1527 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1528 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1529 u8 *pframe = precv_frame->rx_data;
1530 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1531
1532 /* check A3 */
1533 if (!(!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
1534 return _SUCCESS;
1535
1536 if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1537 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1538 _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
1539 }
1540
1541 reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1542
1543 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1544 struct sta_info *psta;
1545 struct sta_priv *pstapriv = &padapter->stapriv;
1546
1547 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1548 if (psta) {
1549 u8 updated = 0;
1550
1551 spin_lock_bh(&pstapriv->asoc_list_lock);
1552 if (!list_empty(&psta->asoc_list)) {
1553 list_del_init(&psta->asoc_list);
1554 pstapriv->asoc_list_cnt--;
1555 updated = ap_free_sta(padapter, psta, false, reason);
1556 }
1557 spin_unlock_bh(&pstapriv->asoc_list_lock);
1558
1559 associated_clients_update(padapter, updated);
1560 }
1561
1562 return _SUCCESS;
1563 } else {
1564 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1565 }
1566 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1567 return _SUCCESS;
1568 }
1569
OnAction_back(struct adapter * padapter,struct recv_frame * precv_frame)1570 unsigned int OnAction_back(struct adapter *padapter, struct recv_frame *precv_frame)
1571 {
1572 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data;
1573 struct sta_info *psta = NULL;
1574 struct recv_reorder_ctrl *preorder_ctrl;
1575 unsigned char *frame_body;
1576 unsigned short tid;
1577 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1578 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1579 u8 *pframe = precv_frame->rx_data;
1580 struct sta_priv *pstapriv = &padapter->stapriv;
1581 /* check RA matches or not */
1582 if (memcmp(myid(&padapter->eeprompriv), mgmt->da, ETH_ALEN))/* for if1, sta/ap mode */
1583 return _SUCCESS;
1584
1585 if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
1586 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1587 return _SUCCESS;
1588
1589 psta = rtw_get_stainfo(pstapriv, mgmt->sa);
1590
1591 if (!psta)
1592 return _SUCCESS;
1593
1594 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1595
1596 if (!pmlmeinfo->HT_enable)
1597 return _SUCCESS;
1598 /* All union members start with an action code, it's ok to use addba_req. */
1599 switch (mgmt->u.action.u.addba_req.action_code) {
1600 case WLAN_ACTION_ADDBA_REQ:
1601 memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2], sizeof(struct ADDBA_request));
1602 tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.addba_req.capab),
1603 IEEE80211_ADDBA_PARAM_TID_MASK);
1604 preorder_ctrl = &psta->recvreorder_ctrl[tid];
1605 preorder_ctrl->indicate_seq = 0xffff;
1606 preorder_ctrl->enable = pmlmeinfo->bAcceptAddbaReq;
1607
1608 issue_action_BA(padapter, mgmt->sa, WLAN_ACTION_ADDBA_RESP,
1609 pmlmeinfo->bAcceptAddbaReq ?
1610 WLAN_STATUS_SUCCESS : WLAN_STATUS_REQUEST_DECLINED);
1611 break;
1612 case WLAN_ACTION_ADDBA_RESP:
1613 tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.addba_resp.capab),
1614 IEEE80211_ADDBA_PARAM_TID_MASK);
1615 if (mgmt->u.action.u.addba_resp.status == 0) { /* successful */
1616 psta->htpriv.agg_enable_bitmap |= BIT(tid);
1617 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1618 } else {
1619 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1620 }
1621 break;
1622 case WLAN_ACTION_DELBA:
1623 tid = u16_get_bits(le16_to_cpu(mgmt->u.action.u.delba.params),
1624 IEEE80211_DELBA_PARAM_TID_MASK);
1625 if (u16_get_bits(le16_to_cpu(mgmt->u.action.u.delba.params),
1626 IEEE80211_DELBA_PARAM_INITIATOR_MASK) == WLAN_BACK_RECIPIENT) {
1627 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1628 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1629 } else {
1630 preorder_ctrl = &psta->recvreorder_ctrl[tid];
1631 preorder_ctrl->enable = false;
1632 preorder_ctrl->indicate_seq = 0xffff;
1633 }
1634 /* todo: how to notify the host while receiving DELETE BA */
1635 break;
1636 default:
1637 break;
1638 }
1639
1640 return _SUCCESS;
1641 }
1642
get_reg_classes_full_count(struct p2p_channels * channel_list)1643 static int get_reg_classes_full_count(struct p2p_channels *channel_list)
1644 {
1645 int cnt = 0;
1646 int i;
1647
1648 for (i = 0; i < channel_list->reg_classes; i++) {
1649 cnt += channel_list->reg_class[i].channels;
1650 }
1651
1652 return cnt;
1653 }
1654
issue_p2p_GO_request(struct adapter * padapter,u8 * raddr)1655 void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
1656 {
1657 unsigned char category = WLAN_CATEGORY_PUBLIC;
1658 u8 action = P2P_PUB_ACTION_ACTION;
1659 __be32 p2poui = cpu_to_be32(P2POUI);
1660 u8 oui_subtype = P2P_GO_NEGO_REQ;
1661 u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
1662 u8 wpsielen = 0, p2pielen = 0;
1663 u16 len_channellist_attr = 0;
1664 struct xmit_frame *pmgntframe;
1665 struct pkt_attrib *pattrib;
1666 unsigned char *pframe;
1667 struct ieee80211_hdr *pwlanhdr;
1668 __le16 *fctrl;
1669 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1670 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1671 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1672
1673 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1674 if (!pmgntframe)
1675 return;
1676
1677 /* update attribute */
1678 pattrib = &pmgntframe->attrib;
1679 update_mgntframe_attrib(padapter, pattrib);
1680
1681 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1682
1683 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1684 pwlanhdr = (struct ieee80211_hdr *)pframe;
1685
1686 fctrl = &pwlanhdr->frame_control;
1687 *(fctrl) = 0;
1688
1689 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
1690 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
1691 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
1692
1693 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1694 pmlmeext->mgnt_seq++;
1695 SetFrameSubType(pframe, WIFI_ACTION);
1696
1697 pframe += sizeof(struct ieee80211_hdr_3addr);
1698 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
1699
1700 pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
1701 pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
1702 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
1703 pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
1704 pwdinfo->negotiation_dialog_token = 1; /* Initialize the dialog value */
1705 pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
1706
1707 /* WPS Section */
1708 wpsielen = 0;
1709 /* WPS OUI */
1710 *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
1711 wpsielen += 4;
1712
1713 /* WPS version */
1714 /* Type: */
1715 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
1716 wpsielen += 2;
1717
1718 /* Length: */
1719 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
1720 wpsielen += 2;
1721
1722 /* Value: */
1723 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
1724
1725 /* Device Password ID */
1726 /* Type: */
1727 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
1728 wpsielen += 2;
1729
1730 /* Length: */
1731 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
1732 wpsielen += 2;
1733
1734 /* Value: */
1735
1736 if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
1737 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
1738 else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
1739 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
1740 else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
1741 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
1742
1743 wpsielen += 2;
1744
1745 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
1746
1747 /* P2P IE Section. */
1748
1749 /* P2P OUI */
1750 p2pielen = 0;
1751 p2pie[p2pielen++] = 0x50;
1752 p2pie[p2pielen++] = 0x6F;
1753 p2pie[p2pielen++] = 0x9A;
1754 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
1755
1756 /* Commented by Albert 20110306 */
1757 /* According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
1758 /* 1. P2P Capability */
1759 /* 2. Group Owner Intent */
1760 /* 3. Configuration Timeout */
1761 /* 4. Listen Channel */
1762 /* 5. Extended Listen Timing */
1763 /* 6. Intended P2P Interface Address */
1764 /* 7. Channel List */
1765 /* 8. P2P Device Info */
1766 /* 9. Operating Channel */
1767
1768 /* P2P Capability */
1769 /* Type: */
1770 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
1771
1772 /* Length: */
1773 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
1774 p2pielen += 2;
1775
1776 /* Value: */
1777 /* Device Capability Bitmap, 1 byte */
1778 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
1779
1780 /* Group Capability Bitmap, 1 byte */
1781 if (pwdinfo->persistent_supported)
1782 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
1783 else
1784 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
1785
1786 /* Group Owner Intent */
1787 /* Type: */
1788 p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
1789
1790 /* Length: */
1791 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
1792 p2pielen += 2;
1793
1794 /* Value: */
1795 /* Todo the tie breaker bit. */
1796 p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
1797
1798 /* Configuration Timeout */
1799 /* Type: */
1800 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
1801
1802 /* Length: */
1803 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
1804 p2pielen += 2;
1805
1806 /* Value: */
1807 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
1808 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
1809
1810 /* Listen Channel */
1811 /* Type: */
1812 p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
1813
1814 /* Length: */
1815 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
1816 p2pielen += 2;
1817
1818 /* Value: */
1819 /* Country String */
1820 p2pie[p2pielen++] = 'X';
1821 p2pie[p2pielen++] = 'X';
1822
1823 /* The third byte should be set to 0x04. */
1824 /* Described in the "Operating Channel Attribute" section. */
1825 p2pie[p2pielen++] = 0x04;
1826
1827 /* Operating Class */
1828 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
1829
1830 /* Channel Number */
1831 p2pie[p2pielen++] = pwdinfo->listen_channel; /* listening channel number */
1832
1833 /* Extended Listen Timing ATTR */
1834 /* Type: */
1835 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
1836
1837 /* Length: */
1838 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
1839 p2pielen += 2;
1840
1841 /* Value: */
1842 /* Availability Period */
1843 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
1844 p2pielen += 2;
1845
1846 /* Availability Interval */
1847 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
1848 p2pielen += 2;
1849
1850 /* Intended P2P Interface Address */
1851 /* Type: */
1852 p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
1853
1854 /* Length: */
1855 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
1856 p2pielen += 2;
1857
1858 /* Value: */
1859 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
1860 p2pielen += ETH_ALEN;
1861
1862 /* Channel List */
1863 /* Type: */
1864 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
1865
1866 /* Length: */
1867 /* Country String(3) */
1868 /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
1869 /* + number of channels in all classes */
1870 len_channellist_attr = 3
1871 + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
1872 + get_reg_classes_full_count(&pmlmeext->channel_list);
1873
1874 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
1875 p2pielen += 2;
1876
1877 /* Value: */
1878 /* Country String */
1879 p2pie[p2pielen++] = 'X';
1880 p2pie[p2pielen++] = 'X';
1881
1882 /* The third byte should be set to 0x04. */
1883 /* Described in the "Operating Channel Attribute" section. */
1884 p2pie[p2pielen++] = 0x04;
1885
1886 /* Channel Entry List */
1887
1888 {
1889 int i, j;
1890 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
1891 /* Operating Class */
1892 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
1893
1894 /* Number of Channels */
1895 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
1896
1897 /* Channel List */
1898 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
1899 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
1900 }
1901 }
1902 }
1903
1904 /* Device Info */
1905 /* Type: */
1906 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
1907
1908 /* Length: */
1909 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
1910 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
1911 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
1912 p2pielen += 2;
1913
1914 /* Value: */
1915 /* P2P Device Address */
1916 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
1917 p2pielen += ETH_ALEN;
1918
1919 /* Config Method */
1920 /* This field should be big endian. Noted by P2P specification. */
1921
1922 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
1923
1924 p2pielen += 2;
1925
1926 /* Primary Device Type */
1927 /* Category ID */
1928 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
1929 p2pielen += 2;
1930
1931 /* OUI */
1932 *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
1933 p2pielen += 4;
1934
1935 /* Sub Category ID */
1936 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
1937 p2pielen += 2;
1938
1939 /* Number of Secondary Device Types */
1940 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
1941
1942 /* Device Name */
1943 /* Type: */
1944 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
1945 p2pielen += 2;
1946
1947 /* Length: */
1948 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
1949 p2pielen += 2;
1950
1951 /* Value: */
1952 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
1953 p2pielen += pwdinfo->device_name_len;
1954
1955 /* Operating Channel */
1956 /* Type: */
1957 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
1958
1959 /* Length: */
1960 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
1961 p2pielen += 2;
1962
1963 /* Value: */
1964 /* Country String */
1965 p2pie[p2pielen++] = 'X';
1966 p2pie[p2pielen++] = 'X';
1967
1968 /* The third byte should be set to 0x04. */
1969 /* Described in the "Operating Channel Attribute" section. */
1970 p2pie[p2pielen++] = 0x04;
1971
1972 /* Operating Class */
1973 p2pie[p2pielen++] = 0x51;
1974
1975 /* Channel Number */
1976 p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
1977
1978 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
1979
1980 pattrib->last_txcmdsz = pattrib->pktlen;
1981
1982 dump_mgntframe(padapter, pmgntframe);
1983 }
1984
issue_p2p_GO_response(struct adapter * padapter,u8 * raddr,u8 * frame_body,uint len,u8 result)1985 static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result)
1986 {
1987 unsigned char category = WLAN_CATEGORY_PUBLIC;
1988 u8 action = P2P_PUB_ACTION_ACTION;
1989 __be32 p2poui = cpu_to_be32(P2POUI);
1990 u8 oui_subtype = P2P_GO_NEGO_RESP;
1991 u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
1992 u8 p2pielen = 0;
1993 uint wpsielen = 0;
1994 u16 wps_devicepassword_id = 0x0000;
1995 __be16 be_tmp;
1996 uint wps_devicepassword_id_len = 0;
1997 u16 len_channellist_attr = 0;
1998
1999 struct xmit_frame *pmgntframe;
2000 struct pkt_attrib *pattrib;
2001 unsigned char *pframe;
2002 struct ieee80211_hdr *pwlanhdr;
2003 __le16 *fctrl;
2004 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2005 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2006 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2007
2008 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2009 if (!pmgntframe)
2010 return;
2011
2012 /* update attribute */
2013 pattrib = &pmgntframe->attrib;
2014 update_mgntframe_attrib(padapter, pattrib);
2015
2016 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2017
2018 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2019 pwlanhdr = (struct ieee80211_hdr *)pframe;
2020
2021 fctrl = &pwlanhdr->frame_control;
2022 *(fctrl) = 0;
2023
2024 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2025 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2026 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
2027
2028 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2029 pmlmeext->mgnt_seq++;
2030 SetFrameSubType(pframe, WIFI_ACTION);
2031
2032 pframe += sizeof(struct ieee80211_hdr_3addr);
2033 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2034
2035 pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2036 pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2037 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2038 pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2039 pwdinfo->negotiation_dialog_token = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
2040 pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
2041
2042 /* Commented by Albert 20110328 */
2043 /* Try to get the device password ID from the WPS IE of group negotiation request frame */
2044 /* WiFi Direct test plan 5.1.15 */
2045 rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
2046 rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
2047 wps_devicepassword_id = be16_to_cpu(be_tmp);
2048
2049 memset(wpsie, 0x00, 255);
2050 wpsielen = 0;
2051
2052 /* WPS Section */
2053 wpsielen = 0;
2054 /* WPS OUI */
2055 *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
2056 wpsielen += 4;
2057
2058 /* WPS version */
2059 /* Type: */
2060 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
2061 wpsielen += 2;
2062
2063 /* Length: */
2064 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
2065 wpsielen += 2;
2066
2067 /* Value: */
2068 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
2069
2070 /* Device Password ID */
2071 /* Type: */
2072 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
2073 wpsielen += 2;
2074
2075 /* Length: */
2076 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
2077 wpsielen += 2;
2078
2079 /* Value: */
2080 if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2081 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
2082 else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2083 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
2084 else
2085 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
2086 wpsielen += 2;
2087
2088 /* Commented by Kurt 20120113 */
2089 /* If some device wants to do p2p handshake without sending prov_disc_req */
2090 /* We have to get peer_req_cm from here. */
2091 if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2092 if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2093 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2094 else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2095 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2096 else
2097 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2098 }
2099
2100 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
2101
2102 /* P2P IE Section. */
2103
2104 /* P2P OUI */
2105 p2pielen = 0;
2106 p2pie[p2pielen++] = 0x50;
2107 p2pie[p2pielen++] = 0x6F;
2108 p2pie[p2pielen++] = 0x9A;
2109 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2110
2111 /* Commented by Albert 20100908 */
2112 /* According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
2113 /* 1. Status */
2114 /* 2. P2P Capability */
2115 /* 3. Group Owner Intent */
2116 /* 4. Configuration Timeout */
2117 /* 5. Operating Channel */
2118 /* 6. Intended P2P Interface Address */
2119 /* 7. Channel List */
2120 /* 8. Device Info */
2121 /* 9. Group ID (Only GO) */
2122
2123 /* ToDo: */
2124
2125 /* P2P Status */
2126 /* Type: */
2127 p2pie[p2pielen++] = P2P_ATTR_STATUS;
2128
2129 /* Length: */
2130 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2131 p2pielen += 2;
2132
2133 /* Value: */
2134 p2pie[p2pielen++] = result;
2135
2136 /* P2P Capability */
2137 /* Type: */
2138 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2139
2140 /* Length: */
2141 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2142 p2pielen += 2;
2143
2144 /* Value: */
2145 /* Device Capability Bitmap, 1 byte */
2146
2147 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2148 /* Commented by Albert 2011/03/08 */
2149 /* According to the P2P specification */
2150 /* if the sending device will be client, the P2P Capability should be reserved of group negotiation response frame */
2151 p2pie[p2pielen++] = 0;
2152 } else {
2153 /* Be group owner or meet the error case */
2154 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2155 }
2156
2157 /* Group Capability Bitmap, 1 byte */
2158 if (pwdinfo->persistent_supported) {
2159 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2160 } else {
2161 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2162 }
2163
2164 /* Group Owner Intent */
2165 /* Type: */
2166 p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
2167
2168 /* Length: */
2169 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2170 p2pielen += 2;
2171
2172 /* Value: */
2173 if (pwdinfo->peer_intent & 0x01) {
2174 /* Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
2175 p2pie[p2pielen++] = (pwdinfo->intent << 1);
2176 } else {
2177 /* Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
2178 p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
2179 }
2180
2181 /* Configuration Timeout */
2182 /* Type: */
2183 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2184
2185 /* Length: */
2186 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2187 p2pielen += 2;
2188
2189 /* Value: */
2190 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
2191 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
2192
2193 /* Operating Channel */
2194 /* Type: */
2195 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2196
2197 /* Length: */
2198 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2199 p2pielen += 2;
2200
2201 /* Value: */
2202 /* Country String */
2203 p2pie[p2pielen++] = 'X';
2204 p2pie[p2pielen++] = 'X';
2205
2206 /* The third byte should be set to 0x04. */
2207 /* Described in the "Operating Channel Attribute" section. */
2208 p2pie[p2pielen++] = 0x04;
2209
2210 /* Operating Class */
2211 p2pie[p2pielen++] = 0x51;
2212
2213 /* Channel Number */
2214 p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
2215
2216 /* Intended P2P Interface Address */
2217 /* Type: */
2218 p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2219
2220 /* Length: */
2221 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2222 p2pielen += 2;
2223
2224 /* Value: */
2225 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2226 p2pielen += ETH_ALEN;
2227
2228 /* Channel List */
2229 /* Type: */
2230 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2231
2232 /* Country String(3) */
2233 /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2234 /* + number of channels in all classes */
2235 len_channellist_attr = 3
2236 + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2237 + get_reg_classes_full_count(&pmlmeext->channel_list);
2238
2239 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2240
2241 p2pielen += 2;
2242
2243 /* Value: */
2244 /* Country String */
2245 p2pie[p2pielen++] = 'X';
2246 p2pie[p2pielen++] = 'X';
2247
2248 /* The third byte should be set to 0x04. */
2249 /* Described in the "Operating Channel Attribute" section. */
2250 p2pie[p2pielen++] = 0x04;
2251
2252 /* Channel Entry List */
2253
2254 {
2255 int i, j;
2256 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2257 /* Operating Class */
2258 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2259
2260 /* Number of Channels */
2261 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2262
2263 /* Channel List */
2264 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2265 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2266 }
2267 }
2268 }
2269
2270 /* Device Info */
2271 /* Type: */
2272 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2273
2274 /* Length: */
2275 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2276 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2277 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2278 p2pielen += 2;
2279
2280 /* Value: */
2281 /* P2P Device Address */
2282 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2283 p2pielen += ETH_ALEN;
2284
2285 /* Config Method */
2286 /* This field should be big endian. Noted by P2P specification. */
2287
2288 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2289
2290 p2pielen += 2;
2291
2292 /* Primary Device Type */
2293 /* Category ID */
2294 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2295 p2pielen += 2;
2296
2297 /* OUI */
2298 *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2299 p2pielen += 4;
2300
2301 /* Sub Category ID */
2302 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2303 p2pielen += 2;
2304
2305 /* Number of Secondary Device Types */
2306 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2307
2308 /* Device Name */
2309 /* Type: */
2310 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2311 p2pielen += 2;
2312
2313 /* Length: */
2314 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2315 p2pielen += 2;
2316
2317 /* Value: */
2318 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2319 p2pielen += pwdinfo->device_name_len;
2320
2321 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2322 /* Group ID Attribute */
2323 /* Type: */
2324 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2325
2326 /* Length: */
2327 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2328 p2pielen += 2;
2329
2330 /* Value: */
2331 /* p2P Device Address */
2332 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2333 p2pielen += ETH_ALEN;
2334
2335 /* SSID */
2336 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2337 p2pielen += pwdinfo->nego_ssidlen;
2338 }
2339
2340 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2341
2342 pattrib->last_txcmdsz = pattrib->pktlen;
2343
2344 dump_mgntframe(padapter, pmgntframe);
2345 }
2346
issue_p2p_GO_confirm(struct adapter * padapter,u8 * raddr,u8 result)2347 static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result)
2348 {
2349 unsigned char category = WLAN_CATEGORY_PUBLIC;
2350 u8 action = P2P_PUB_ACTION_ACTION;
2351 __be32 p2poui = cpu_to_be32(P2POUI);
2352 u8 oui_subtype = P2P_GO_NEGO_CONF;
2353 u8 p2pie[255] = { 0x00 };
2354 u8 p2pielen = 0;
2355
2356 struct xmit_frame *pmgntframe;
2357 struct pkt_attrib *pattrib;
2358 unsigned char *pframe;
2359 struct ieee80211_hdr *pwlanhdr;
2360 __le16 *fctrl;
2361 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2362 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2363 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2364
2365 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2366 if (!pmgntframe)
2367 return;
2368
2369 /* update attribute */
2370 pattrib = &pmgntframe->attrib;
2371 update_mgntframe_attrib(padapter, pattrib);
2372
2373 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2374
2375 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2376 pwlanhdr = (struct ieee80211_hdr *)pframe;
2377
2378 fctrl = &pwlanhdr->frame_control;
2379 *(fctrl) = 0;
2380
2381 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2382 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2383 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
2384
2385 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2386 pmlmeext->mgnt_seq++;
2387 SetFrameSubType(pframe, WIFI_ACTION);
2388
2389 pframe += sizeof(struct ieee80211_hdr_3addr);
2390 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2391
2392 pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2393 pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2394 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2395 pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2396 pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &pattrib->pktlen);
2397
2398 /* P2P IE Section. */
2399
2400 /* P2P OUI */
2401 p2pielen = 0;
2402 p2pie[p2pielen++] = 0x50;
2403 p2pie[p2pielen++] = 0x6F;
2404 p2pie[p2pielen++] = 0x9A;
2405 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2406
2407 /* Commented by Albert 20110306 */
2408 /* According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
2409 /* 1. Status */
2410 /* 2. P2P Capability */
2411 /* 3. Operating Channel */
2412 /* 4. Channel List */
2413 /* 5. Group ID (if this WiFi is GO) */
2414
2415 /* P2P Status */
2416 /* Type: */
2417 p2pie[p2pielen++] = P2P_ATTR_STATUS;
2418
2419 /* Length: */
2420 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2421 p2pielen += 2;
2422
2423 /* Value: */
2424 p2pie[p2pielen++] = result;
2425
2426 /* P2P Capability */
2427 /* Type: */
2428 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2429
2430 /* Length: */
2431 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2432 p2pielen += 2;
2433
2434 /* Value: */
2435 /* Device Capability Bitmap, 1 byte */
2436 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2437
2438 /* Group Capability Bitmap, 1 byte */
2439 if (pwdinfo->persistent_supported)
2440 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2441 else
2442 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2443
2444 /* Operating Channel */
2445 /* Type: */
2446 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2447
2448 /* Length: */
2449 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2450 p2pielen += 2;
2451
2452 /* Value: */
2453 /* Country String */
2454 p2pie[p2pielen++] = 'X';
2455 p2pie[p2pielen++] = 'X';
2456
2457 /* The third byte should be set to 0x04. */
2458 /* Described in the "Operating Channel Attribute" section. */
2459 p2pie[p2pielen++] = 0x04;
2460
2461 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2462 /* Operating Class */
2463 p2pie[p2pielen++] = 0x51;
2464 p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
2465 } else {
2466 /* Operating Class */
2467 p2pie[p2pielen++] = 0x51;
2468
2469 /* Channel Number */
2470 p2pie[p2pielen++] = pwdinfo->operating_channel; /* Use the listen channel as the operating channel */
2471 }
2472
2473 /* Channel List */
2474 /* Type: */
2475 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2476
2477 /* Length: */
2478 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(pwdinfo->channel_list_attr_len);
2479 p2pielen += 2;
2480
2481 /* Value: */
2482 memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len);
2483 p2pielen += pwdinfo->channel_list_attr_len;
2484
2485 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2486 /* Group ID Attribute */
2487 /* Type: */
2488 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2489
2490 /* Length: */
2491 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2492 p2pielen += 2;
2493
2494 /* Value: */
2495 /* p2P Device Address */
2496 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2497 p2pielen += ETH_ALEN;
2498
2499 /* SSID */
2500 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2501 p2pielen += pwdinfo->nego_ssidlen;
2502 }
2503 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2504 pattrib->last_txcmdsz = pattrib->pktlen;
2505 dump_mgntframe(padapter, pmgntframe);
2506 }
2507
issue_p2p_invitation_request(struct adapter * padapter,u8 * raddr)2508 void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr)
2509 {
2510 unsigned char category = WLAN_CATEGORY_PUBLIC;
2511 u8 action = P2P_PUB_ACTION_ACTION;
2512 __be32 p2poui = cpu_to_be32(P2POUI);
2513 u8 oui_subtype = P2P_INVIT_REQ;
2514 u8 p2pie[255] = { 0x00 };
2515 u8 p2pielen = 0;
2516 u8 dialogToken = 3;
2517 u16 len_channellist_attr = 0;
2518 struct xmit_frame *pmgntframe;
2519 struct pkt_attrib *pattrib;
2520 unsigned char *pframe;
2521 struct ieee80211_hdr *pwlanhdr;
2522 __le16 *fctrl;
2523 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2524 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2525 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2526
2527 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2528 if (!pmgntframe)
2529 return;
2530
2531 /* update attribute */
2532 pattrib = &pmgntframe->attrib;
2533 update_mgntframe_attrib(padapter, pattrib);
2534
2535 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2536
2537 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2538 pwlanhdr = (struct ieee80211_hdr *)pframe;
2539
2540 fctrl = &pwlanhdr->frame_control;
2541 *(fctrl) = 0;
2542
2543 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2544 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2545 memcpy(pwlanhdr->addr3, raddr, ETH_ALEN);
2546
2547 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2548 pmlmeext->mgnt_seq++;
2549 SetFrameSubType(pframe, WIFI_ACTION);
2550
2551 pframe += sizeof(struct ieee80211_hdr_3addr);
2552 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2553
2554 pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2555 pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2556 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2557 pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2558 pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
2559
2560 /* P2P IE Section. */
2561
2562 /* P2P OUI */
2563 p2pielen = 0;
2564 p2pie[p2pielen++] = 0x50;
2565 p2pie[p2pielen++] = 0x6F;
2566 p2pie[p2pielen++] = 0x9A;
2567 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2568
2569 /* Commented by Albert 20101011 */
2570 /* According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */
2571 /* 1. Configuration Timeout */
2572 /* 2. Invitation Flags */
2573 /* 3. Operating Channel (Only GO) */
2574 /* 4. P2P Group BSSID (Should be included if I am the GO) */
2575 /* 5. Channel List */
2576 /* 6. P2P Group ID */
2577 /* 7. P2P Device Info */
2578
2579 /* Configuration Timeout */
2580 /* Type: */
2581 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2582
2583 /* Length: */
2584 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2585 p2pielen += 2;
2586
2587 /* Value: */
2588 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
2589 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
2590
2591 /* Invitation Flags */
2592 /* Type: */
2593 p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
2594
2595 /* Length: */
2596 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2597 p2pielen += 2;
2598
2599 /* Value: */
2600 p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
2601
2602 /* Operating Channel */
2603 /* Type: */
2604 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2605
2606 /* Length: */
2607 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2608 p2pielen += 2;
2609
2610 /* Value: */
2611 /* Country String */
2612 p2pie[p2pielen++] = 'X';
2613 p2pie[p2pielen++] = 'X';
2614
2615 /* The third byte should be set to 0x04. */
2616 /* Described in the "Operating Channel Attribute" section. */
2617 p2pie[p2pielen++] = 0x04;
2618
2619 /* Operating Class */
2620 p2pie[p2pielen++] = 0x51;
2621
2622 /* Channel Number */
2623 p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch; /* operating channel number */
2624
2625 if (!memcmp(myid(&padapter->eeprompriv), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
2626 /* P2P Group BSSID */
2627 /* Type: */
2628 p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
2629
2630 /* Length: */
2631 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2632 p2pielen += 2;
2633
2634 /* Value: */
2635 /* P2P Device Address for GO */
2636 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
2637 p2pielen += ETH_ALEN;
2638 }
2639
2640 /* Channel List */
2641 /* Type: */
2642 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2643
2644 /* Length: */
2645 /* Country String(3) */
2646 /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2647 /* + number of channels in all classes */
2648 len_channellist_attr = 3
2649 + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2650 + get_reg_classes_full_count(&pmlmeext->channel_list);
2651
2652 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2653
2654 p2pielen += 2;
2655
2656 /* Value: */
2657 /* Country String */
2658 p2pie[p2pielen++] = 'X';
2659 p2pie[p2pielen++] = 'X';
2660
2661 /* The third byte should be set to 0x04. */
2662 /* Described in the "Operating Channel Attribute" section. */
2663 p2pie[p2pielen++] = 0x04;
2664
2665 /* Channel Entry List */
2666 {
2667 int i, j;
2668 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2669 /* Operating Class */
2670 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2671
2672 /* Number of Channels */
2673 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2674
2675 /* Channel List */
2676 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2677 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2678 }
2679 }
2680 }
2681
2682 /* P2P Group ID */
2683 /* Type: */
2684 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2685
2686 /* Length: */
2687 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
2688 p2pielen += 2;
2689
2690 /* Value: */
2691 /* P2P Device Address for GO */
2692 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
2693 p2pielen += ETH_ALEN;
2694
2695 /* SSID */
2696 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen);
2697 p2pielen += pwdinfo->invitereq_info.ssidlen;
2698
2699 /* Device Info */
2700 /* Type: */
2701 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2702
2703 /* Length: */
2704 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2705 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2706 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2707 p2pielen += 2;
2708
2709 /* Value: */
2710 /* P2P Device Address */
2711 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2712 p2pielen += ETH_ALEN;
2713
2714 /* Config Method */
2715 /* This field should be big endian. Noted by P2P specification. */
2716 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
2717 p2pielen += 2;
2718
2719 /* Primary Device Type */
2720 /* Category ID */
2721 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2722 p2pielen += 2;
2723
2724 /* OUI */
2725 *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2726 p2pielen += 4;
2727
2728 /* Sub Category ID */
2729 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2730 p2pielen += 2;
2731
2732 /* Number of Secondary Device Types */
2733 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2734
2735 /* Device Name */
2736 /* Type: */
2737 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2738 p2pielen += 2;
2739
2740 /* Length: */
2741 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2742 p2pielen += 2;
2743
2744 /* Value: */
2745 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2746 p2pielen += pwdinfo->device_name_len;
2747
2748 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2749
2750 pattrib->last_txcmdsz = pattrib->pktlen;
2751
2752 dump_mgntframe(padapter, pmgntframe);
2753 }
2754
issue_p2p_invitation_response(struct adapter * padapter,u8 * raddr,u8 dialogToken,u8 status_code)2755 void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code)
2756 {
2757 unsigned char category = WLAN_CATEGORY_PUBLIC;
2758 u8 action = P2P_PUB_ACTION_ACTION;
2759 __be32 p2poui = cpu_to_be32(P2POUI);
2760 u8 oui_subtype = P2P_INVIT_RESP;
2761 u8 p2pie[255] = { 0x00 };
2762 u8 p2pielen = 0;
2763 u16 len_channellist_attr = 0;
2764 struct xmit_frame *pmgntframe;
2765 struct pkt_attrib *pattrib;
2766 unsigned char *pframe;
2767 struct ieee80211_hdr *pwlanhdr;
2768 __le16 *fctrl;
2769 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2770 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2771 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2772
2773 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2774 if (!pmgntframe)
2775 return;
2776
2777 /* update attribute */
2778 pattrib = &pmgntframe->attrib;
2779 update_mgntframe_attrib(padapter, pattrib);
2780
2781 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2782
2783 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2784 pwlanhdr = (struct ieee80211_hdr *)pframe;
2785
2786 fctrl = &pwlanhdr->frame_control;
2787 *(fctrl) = 0;
2788
2789 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2790 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2791 memcpy(pwlanhdr->addr3, raddr, ETH_ALEN);
2792
2793 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2794 pmlmeext->mgnt_seq++;
2795 SetFrameSubType(pframe, WIFI_ACTION);
2796
2797 pframe += sizeof(struct ieee80211_hdr_3addr);
2798 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2799
2800 pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2801 pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2802 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2803 pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2804 pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
2805
2806 /* P2P IE Section. */
2807
2808 /* P2P OUI */
2809 p2pielen = 0;
2810 p2pie[p2pielen++] = 0x50;
2811 p2pie[p2pielen++] = 0x6F;
2812 p2pie[p2pielen++] = 0x9A;
2813 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2814
2815 /* Commented by Albert 20101005 */
2816 /* According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
2817 /* 1. Status */
2818 /* 2. Configuration Timeout */
2819 /* 3. Operating Channel (Only GO) */
2820 /* 4. P2P Group BSSID (Only GO) */
2821 /* 5. Channel List */
2822
2823 /* P2P Status */
2824 /* Type: */
2825 p2pie[p2pielen++] = P2P_ATTR_STATUS;
2826
2827 /* Length: */
2828 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2829 p2pielen += 2;
2830
2831 /* Value: */
2832 /* When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
2833 /* Sent the event receiving the P2P Invitation Req frame to DMP UI. */
2834 /* DMP had to compare the MAC address to find out the profile. */
2835 /* So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
2836 /* If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */
2837 /* to NB to rebuild the persistent group. */
2838 p2pie[p2pielen++] = status_code;
2839
2840 /* Configuration Timeout */
2841 /* Type: */
2842 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2843
2844 /* Length: */
2845 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2846 p2pielen += 2;
2847
2848 /* Value: */
2849 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
2850 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
2851
2852 if (status_code == P2P_STATUS_SUCCESS) {
2853 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2854 /* The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
2855 /* In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
2856 /* First one is operating channel attribute. */
2857 /* Second one is P2P Group BSSID attribute. */
2858
2859 /* Operating Channel */
2860 /* Type: */
2861 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2862
2863 /* Length: */
2864 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2865 p2pielen += 2;
2866
2867 /* Value: */
2868 /* Country String */
2869 p2pie[p2pielen++] = 'X';
2870 p2pie[p2pielen++] = 'X';
2871
2872 /* The third byte should be set to 0x04. */
2873 /* Described in the "Operating Channel Attribute" section. */
2874 p2pie[p2pielen++] = 0x04;
2875
2876 /* Operating Class */
2877 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
2878
2879 /* Channel Number */
2880 p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
2881
2882 /* P2P Group BSSID */
2883 /* Type: */
2884 p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
2885
2886 /* Length: */
2887 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2888 p2pielen += 2;
2889
2890 /* Value: */
2891 /* P2P Device Address for GO */
2892 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2893 p2pielen += ETH_ALEN;
2894 }
2895
2896 /* Channel List */
2897 /* Type: */
2898 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2899
2900 /* Length: */
2901 /* Country String(3) */
2902 /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2903 /* + number of channels in all classes */
2904 len_channellist_attr = 3
2905 + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2906 + get_reg_classes_full_count(&pmlmeext->channel_list);
2907
2908 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2909 p2pielen += 2;
2910
2911 /* Value: */
2912 /* Country String */
2913 p2pie[p2pielen++] = 'X';
2914 p2pie[p2pielen++] = 'X';
2915
2916 /* The third byte should be set to 0x04. */
2917 /* Described in the "Operating Channel Attribute" section. */
2918 p2pie[p2pielen++] = 0x04;
2919
2920 /* Channel Entry List */
2921 {
2922 int i, j;
2923 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2924 /* Operating Class */
2925 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2926
2927 /* Number of Channels */
2928 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2929
2930 /* Channel List */
2931 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2932 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2933 }
2934 }
2935 }
2936 }
2937
2938 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2939
2940 pattrib->last_txcmdsz = pattrib->pktlen;
2941
2942 dump_mgntframe(padapter, pmgntframe);
2943 }
2944
issue_p2p_provision_request(struct adapter * padapter,u8 * pssid,u8 ussidlen,u8 * pdev_raddr)2945 void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
2946 {
2947 unsigned char category = WLAN_CATEGORY_PUBLIC;
2948 u8 action = P2P_PUB_ACTION_ACTION;
2949 u8 dialogToken = 1;
2950 u8 oui_subtype = P2P_PROVISION_DISC_REQ;
2951 u8 wpsie[100] = { 0x00 };
2952 u8 wpsielen = 0;
2953 __be32 p2poui = cpu_to_be32(P2POUI);
2954 u32 p2pielen = 0;
2955 struct xmit_frame *pmgntframe;
2956 struct pkt_attrib *pattrib;
2957 unsigned char *pframe;
2958 struct ieee80211_hdr *pwlanhdr;
2959 __le16 *fctrl;
2960 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2961 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2962 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2963
2964 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2965 if (!pmgntframe)
2966 return;
2967
2968 /* update attribute */
2969 pattrib = &pmgntframe->attrib;
2970 update_mgntframe_attrib(padapter, pattrib);
2971
2972 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2973
2974 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2975 pwlanhdr = (struct ieee80211_hdr *)pframe;
2976
2977 fctrl = &pwlanhdr->frame_control;
2978 *(fctrl) = 0;
2979
2980 memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
2981 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2982 memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
2983
2984 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2985 pmlmeext->mgnt_seq++;
2986 SetFrameSubType(pframe, WIFI_ACTION);
2987
2988 pframe += sizeof(struct ieee80211_hdr_3addr);
2989 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2990
2991 pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
2992 pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
2993 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
2994 pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
2995 pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
2996
2997 p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr);
2998
2999 pframe += p2pielen;
3000 pattrib->pktlen += p2pielen;
3001
3002 wpsielen = 0;
3003 /* WPS OUI */
3004 *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3005 wpsielen += 4;
3006
3007 /* WPS version */
3008 /* Type: */
3009 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3010 wpsielen += 2;
3011
3012 /* Length: */
3013 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3014 wpsielen += 2;
3015
3016 /* Value: */
3017 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3018
3019 /* Config Method */
3020 /* Type: */
3021 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3022 wpsielen += 2;
3023
3024 /* Length: */
3025 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3026 wpsielen += 2;
3027
3028 /* Value: */
3029 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
3030 wpsielen += 2;
3031
3032 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3033
3034 pattrib->last_txcmdsz = pattrib->pktlen;
3035
3036 dump_mgntframe(padapter, pmgntframe);
3037 }
3038
is_matched_in_profilelist(u8 * peermacaddr,struct profile_info * profileinfo)3039 static u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo)
3040 {
3041 u8 i, match_result = 0;
3042
3043 for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
3044 if (!memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
3045 match_result = 1;
3046 break;
3047 }
3048 }
3049 return match_result;
3050 }
3051
issue_probersp_p2p(struct adapter * padapter,unsigned char * da)3052 void issue_probersp_p2p(struct adapter *padapter, unsigned char *da)
3053 {
3054 struct xmit_frame *pmgntframe;
3055 struct pkt_attrib *pattrib;
3056 unsigned char *pframe;
3057 struct ieee80211_hdr *pwlanhdr;
3058 __le16 *fctrl;
3059 unsigned char *mac;
3060 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3061 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3062 u16 beacon_interval = 100;
3063 u16 capInfo = 0;
3064 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3065 u8 wpsie[255] = { 0x00 };
3066 u32 wpsielen = 0, p2pielen = 0;
3067
3068 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3069 if (!pmgntframe)
3070 return;
3071
3072 /* update attribute */
3073 pattrib = &pmgntframe->attrib;
3074 update_mgntframe_attrib(padapter, pattrib);
3075
3076 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3077
3078 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3079 pwlanhdr = (struct ieee80211_hdr *)pframe;
3080
3081 mac = myid(&padapter->eeprompriv);
3082
3083 fctrl = &pwlanhdr->frame_control;
3084 *(fctrl) = 0;
3085 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3086 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
3087
3088 /* Use the device address for BSSID field. */
3089 memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
3090
3091 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3092 pmlmeext->mgnt_seq++;
3093 SetFrameSubType(fctrl, WIFI_PROBERSP);
3094
3095 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3096 pattrib->pktlen = pattrib->hdrlen;
3097 pframe += pattrib->hdrlen;
3098
3099 /* timestamp will be inserted by hardware */
3100 pframe += 8;
3101 pattrib->pktlen += 8;
3102
3103 /* beacon interval: 2 bytes */
3104 memcpy(pframe, (unsigned char *)&beacon_interval, 2);
3105 pframe += 2;
3106 pattrib->pktlen += 2;
3107
3108 /* capability info: 2 bytes */
3109 /* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
3110 capInfo |= cap_ShortPremble;
3111 capInfo |= cap_ShortSlot;
3112
3113 memcpy(pframe, (unsigned char *)&capInfo, 2);
3114 pframe += 2;
3115 pattrib->pktlen += 2;
3116
3117 /* SSID */
3118 pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
3119
3120 /* supported rates... */
3121 /* Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3122 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
3123
3124 /* DS parameter set */
3125 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
3126
3127 /* Todo: WPS IE */
3128 /* Noted by Albert 20100907 */
3129 /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */
3130
3131 wpsielen = 0;
3132 /* WPS OUI */
3133 *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3134 wpsielen += 4;
3135
3136 /* WPS version */
3137 /* Type: */
3138 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3139 wpsielen += 2;
3140
3141 /* Length: */
3142 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3143 wpsielen += 2;
3144
3145 /* Value: */
3146 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3147
3148 /* WiFi Simple Config State */
3149 /* Type: */
3150 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
3151 wpsielen += 2;
3152
3153 /* Length: */
3154 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3155 wpsielen += 2;
3156
3157 /* Value: */
3158 wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG; /* Not Configured. */
3159
3160 /* Response Type */
3161 /* Type: */
3162 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
3163 wpsielen += 2;
3164
3165 /* Length: */
3166 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3167 wpsielen += 2;
3168
3169 /* Value: */
3170 wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
3171
3172 /* UUID-E */
3173 /* Type: */
3174 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3175 wpsielen += 2;
3176
3177 /* Length: */
3178 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
3179 wpsielen += 2;
3180
3181 /* Value: */
3182 memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3183 wpsielen += 0x10;
3184
3185 /* Manufacturer */
3186 /* Type: */
3187 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
3188 wpsielen += 2;
3189
3190 /* Length: */
3191 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);
3192 wpsielen += 2;
3193
3194 /* Value: */
3195 memcpy(wpsie + wpsielen, "Realtek", 7);
3196 wpsielen += 7;
3197
3198 /* Model Name */
3199 /* Type: */
3200 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
3201 wpsielen += 2;
3202
3203 /* Length: */
3204 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);
3205 wpsielen += 2;
3206
3207 /* Value: */
3208 memcpy(wpsie + wpsielen, "8188EU", 6);
3209 wpsielen += 6;
3210
3211 /* Model Number */
3212 /* Type: */
3213 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
3214 wpsielen += 2;
3215
3216 /* Length: */
3217 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3218 wpsielen += 2;
3219
3220 /* Value: */
3221 wpsie[wpsielen++] = 0x31; /* character 1 */
3222
3223 /* Serial Number */
3224 /* Type: */
3225 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
3226 wpsielen += 2;
3227
3228 /* Length: */
3229 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
3230 wpsielen += 2;
3231
3232 /* Value: */
3233 memcpy(wpsie + wpsielen, "123456", ETH_ALEN);
3234 wpsielen += ETH_ALEN;
3235
3236 /* Primary Device Type */
3237 /* Type: */
3238 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3239 wpsielen += 2;
3240
3241 /* Length: */
3242 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
3243 wpsielen += 2;
3244
3245 /* Value: */
3246 /* Category ID */
3247 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
3248 wpsielen += 2;
3249
3250 /* OUI */
3251 *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
3252 wpsielen += 4;
3253
3254 /* Sub Category ID */
3255 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
3256 wpsielen += 2;
3257
3258 /* Device Name */
3259 /* Type: */
3260 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3261 wpsielen += 2;
3262
3263 /* Length: */
3264 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
3265 wpsielen += 2;
3266
3267 /* Value: */
3268 if (pwdinfo->device_name_len) {
3269 memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
3270 wpsielen += pwdinfo->device_name_len;
3271 }
3272
3273 /* Config Method */
3274 /* Type: */
3275 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3276 wpsielen += 2;
3277
3278 /* Length: */
3279 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3280 wpsielen += 2;
3281
3282 /* Value: */
3283 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
3284 wpsielen += 2;
3285
3286 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3287
3288 p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
3289 pframe += p2pielen;
3290 pattrib->pktlen += p2pielen;
3291
3292 pattrib->last_txcmdsz = pattrib->pktlen;
3293
3294 dump_mgntframe(padapter, pmgntframe);
3295 }
3296
_issue_probereq_p2p(struct adapter * padapter,u8 * da,int wait_ack)3297 static int _issue_probereq_p2p(struct adapter *padapter, u8 *da, int wait_ack)
3298 {
3299 int ret = _FAIL;
3300 struct xmit_frame *pmgntframe;
3301 struct pkt_attrib *pattrib;
3302 unsigned char *pframe;
3303 struct ieee80211_hdr *pwlanhdr;
3304 __le16 *fctrl;
3305 unsigned char *mac;
3306 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3307 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3308 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3309 u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
3310 u16 wpsielen = 0, p2pielen = 0;
3311 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3312
3313 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3314 if (!pmgntframe)
3315 goto exit;
3316
3317 /* update attribute */
3318 pattrib = &pmgntframe->attrib;
3319 update_mgntframe_attrib(padapter, pattrib);
3320
3321 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3322
3323 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3324 pwlanhdr = (struct ieee80211_hdr *)pframe;
3325
3326 mac = myid(&padapter->eeprompriv);
3327
3328 fctrl = &pwlanhdr->frame_control;
3329 *(fctrl) = 0;
3330
3331 if (da) {
3332 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3333 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
3334 } else {
3335 if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
3336 /* This two flags will be set when this is only the P2P client mode. */
3337 memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
3338 memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
3339 } else {
3340 /* broadcast probe request frame */
3341 eth_broadcast_addr(pwlanhdr->addr1);
3342 eth_broadcast_addr(pwlanhdr->addr3);
3343 }
3344 }
3345 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
3346
3347 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3348 pmlmeext->mgnt_seq++;
3349 SetFrameSubType(pframe, WIFI_PROBEREQ);
3350
3351 pframe += sizeof(struct ieee80211_hdr_3addr);
3352 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3353
3354 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
3355 pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &pattrib->pktlen);
3356 else
3357 pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
3358
3359 /* Use the OFDM rate in the P2P probe request frame. (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
3360 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
3361
3362 /* WPS IE */
3363 /* Noted by Albert 20110221 */
3364 /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */
3365
3366 wpsielen = 0;
3367 /* WPS OUI */
3368 *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3369 wpsielen += 4;
3370
3371 /* WPS version */
3372 /* Type: */
3373 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3374 wpsielen += 2;
3375
3376 /* Length: */
3377 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3378 wpsielen += 2;
3379
3380 /* Value: */
3381 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3382
3383 if (!pmlmepriv->wps_probe_req_ie) {
3384 /* UUID-E */
3385 /* Type: */
3386 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3387 wpsielen += 2;
3388
3389 /* Length: */
3390 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
3391 wpsielen += 2;
3392
3393 /* Value: */
3394 memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3395 wpsielen += 0x10;
3396
3397 /* Config Method */
3398 /* Type: */
3399 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3400 wpsielen += 2;
3401
3402 /* Length: */
3403 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3404 wpsielen += 2;
3405
3406 /* Value: */
3407 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
3408 wpsielen += 2;
3409 }
3410
3411 /* Device Name */
3412 /* Type: */
3413 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3414 wpsielen += 2;
3415
3416 /* Length: */
3417 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
3418 wpsielen += 2;
3419
3420 /* Value: */
3421 memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
3422 wpsielen += pwdinfo->device_name_len;
3423
3424 /* Primary Device Type */
3425 /* Type: */
3426 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3427 wpsielen += 2;
3428
3429 /* Length: */
3430 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
3431 wpsielen += 2;
3432
3433 /* Value: */
3434 /* Category ID */
3435 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
3436 wpsielen += 2;
3437
3438 /* OUI */
3439 *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
3440 wpsielen += 4;
3441
3442 /* Sub Category ID */
3443 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
3444 wpsielen += 2;
3445
3446 /* Device Password ID */
3447 /* Type: */
3448 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
3449 wpsielen += 2;
3450
3451 /* Length: */
3452 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3453 wpsielen += 2;
3454
3455 /* Value: */
3456 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); /* Registrar-specified */
3457 wpsielen += 2;
3458
3459 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3460
3461 /* P2P OUI */
3462 p2pielen = 0;
3463 p2pie[p2pielen++] = 0x50;
3464 p2pie[p2pielen++] = 0x6F;
3465 p2pie[p2pielen++] = 0x9A;
3466 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
3467
3468 /* Commented by Albert 20110221 */
3469 /* According to the P2P Specification, the probe request frame should contain 5 P2P attributes */
3470 /* 1. P2P Capability */
3471 /* 2. P2P Device ID if this probe request wants to find the specific P2P device */
3472 /* 3. Listen Channel */
3473 /* 4. Extended Listen Timing */
3474 /* 5. Operating Channel if this WiFi is working as the group owner now */
3475
3476 /* P2P Capability */
3477 /* Type: */
3478 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
3479
3480 /* Length: */
3481 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
3482 p2pielen += 2;
3483
3484 /* Value: */
3485 /* Device Capability Bitmap, 1 byte */
3486 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
3487
3488 /* Group Capability Bitmap, 1 byte */
3489 if (pwdinfo->persistent_supported)
3490 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
3491 else
3492 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
3493
3494 /* Listen Channel */
3495 /* Type: */
3496 p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
3497
3498 /* Length: */
3499 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3500 p2pielen += 2;
3501
3502 /* Value: */
3503 /* Country String */
3504 p2pie[p2pielen++] = 'X';
3505 p2pie[p2pielen++] = 'X';
3506
3507 /* The third byte should be set to 0x04. */
3508 /* Described in the "Operating Channel Attribute" section. */
3509 p2pie[p2pielen++] = 0x04;
3510
3511 /* Operating Class */
3512 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
3513
3514 /* Channel Number */
3515 p2pie[p2pielen++] = pwdinfo->listen_channel; /* listen channel */
3516
3517 /* Extended Listen Timing */
3518 /* Type: */
3519 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
3520
3521 /* Length: */
3522 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
3523 p2pielen += 2;
3524
3525 /* Value: */
3526 /* Availability Period */
3527 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
3528 p2pielen += 2;
3529
3530 /* Availability Interval */
3531 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
3532 p2pielen += 2;
3533
3534 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3535 /* Operating Channel (if this WiFi is working as the group owner now) */
3536 /* Type: */
3537 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3538
3539 /* Length: */
3540 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3541 p2pielen += 2;
3542
3543 /* Value: */
3544 /* Country String */
3545 p2pie[p2pielen++] = 'X';
3546 p2pie[p2pielen++] = 'X';
3547
3548 /* The third byte should be set to 0x04. */
3549 /* Described in the "Operating Channel Attribute" section. */
3550 p2pie[p2pielen++] = 0x04;
3551
3552 /* Operating Class */
3553 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
3554
3555 /* Channel Number */
3556 p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
3557 }
3558
3559 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
3560
3561 if (pmlmepriv->wps_probe_req_ie) {
3562 /* WPS IE */
3563 memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
3564 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
3565 pframe += pmlmepriv->wps_probe_req_ie_len;
3566 }
3567
3568 pattrib->last_txcmdsz = pattrib->pktlen;
3569
3570 if (wait_ack) {
3571 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3572 } else {
3573 dump_mgntframe(padapter, pmgntframe);
3574 ret = _SUCCESS;
3575 }
3576
3577 exit:
3578 return ret;
3579 }
3580
issue_probereq_p2p(struct adapter * adapter,u8 * da)3581 inline void issue_probereq_p2p(struct adapter *adapter, u8 *da)
3582 {
3583 _issue_probereq_p2p(adapter, da, false);
3584 }
3585
rtw_action_public_decache(struct recv_frame * recv_frame,s32 token)3586 static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
3587 {
3588 struct adapter *adapter = recv_frame->adapter;
3589 struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
3590 u8 *frame = recv_frame->rx_data;
3591 u16 seq_ctrl = ((recv_frame->attrib.seq_num & 0xffff) << 4) |
3592 (recv_frame->attrib.frag_num & 0xf);
3593
3594 if (GetRetry(frame)) {
3595 if (token >= 0) {
3596 if ((seq_ctrl == mlmeext->action_public_rxseq) &&
3597 (token == mlmeext->action_public_dialog_token))
3598 return _FAIL;
3599 } else {
3600 if (seq_ctrl == mlmeext->action_public_rxseq)
3601 return _FAIL;
3602 }
3603 }
3604
3605 mlmeext->action_public_rxseq = seq_ctrl;
3606
3607 if (token >= 0)
3608 mlmeext->action_public_dialog_token = token;
3609
3610 return _SUCCESS;
3611 }
3612
on_action_public_p2p(struct recv_frame * precv_frame)3613 static unsigned int on_action_public_p2p(struct recv_frame *precv_frame)
3614 {
3615 u8 *pframe = precv_frame->rx_data;
3616 u8 *frame_body;
3617 u8 dialogToken = 0;
3618 struct adapter *padapter = precv_frame->adapter;
3619 uint len = precv_frame->len;
3620 u8 *p2p_ie;
3621 u32 p2p_ielen;
3622 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3623 u8 result = P2P_STATUS_SUCCESS;
3624 u8 empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3625
3626 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3627
3628 dialogToken = frame_body[7];
3629
3630 if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
3631 return _FAIL;
3632
3633 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
3634 /* Do nothing if the driver doesn't enable the P2P function. */
3635 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
3636 return _SUCCESS;
3637
3638 len -= sizeof(struct ieee80211_hdr_3addr);
3639
3640 switch (frame_body[6]) { /* OUI Subtype */
3641 case P2P_GO_NEGO_REQ:
3642 memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3643
3644 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
3645 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3646
3647 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) {
3648 /* Commented by Albert 20110526 */
3649 /* In this case, this means the previous nego fail doesn't be reset yet. */
3650 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3651 /* Restore the previous p2p state */
3652 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3653 }
3654
3655 /* Commented by Kurt 20110902 */
3656 /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
3657 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
3658 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3659
3660 /* Commented by Kurt 20120113 */
3661 /* Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
3662 if (!memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))
3663 memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
3664
3665 result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);
3666 issue_p2p_GO_response(padapter, GetAddr2Ptr(pframe), frame_body, len, result);
3667
3668 /* Commented by Albert 20110718 */
3669 /* No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
3670 _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3671 break;
3672 case P2P_GO_NEGO_RESP:
3673 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
3674 /* Commented by Albert 20110425 */
3675 /* The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
3676 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3677 pwdinfo->nego_req_info.benable = false;
3678 result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len);
3679 issue_p2p_GO_confirm(pwdinfo->padapter, GetAddr2Ptr(pframe), result);
3680 if (result == P2P_STATUS_SUCCESS) {
3681 if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
3682 pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
3683 pwdinfo->p2p_info.scan_op_ch_only = 1;
3684 _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
3685 }
3686 }
3687 /* Reset the dialog token for group negotiation frames. */
3688 pwdinfo->negotiation_dialog_token = 1;
3689 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3690 _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3691 }
3692 break;
3693 case P2P_GO_NEGO_CONF:
3694 result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len);
3695 if (result == P2P_STATUS_SUCCESS) {
3696 if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
3697 pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
3698 pwdinfo->p2p_info.scan_op_ch_only = 1;
3699 _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
3700 }
3701 }
3702 break;
3703 case P2P_INVIT_REQ:
3704 /* Added by Albert 2010/10/05 */
3705 /* Received the P2P Invite Request frame. */
3706
3707 p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
3708 if (p2p_ie) {
3709 /* Parse the necessary information from the P2P Invitation Request frame. */
3710 /* For example: The MAC address of sending this P2P Invitation Request frame. */
3711 u32 attr_contentlen = 0;
3712 u8 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3713 struct group_id_info group_id;
3714 u8 invitation_flag = 0;
3715
3716 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
3717 if (attr_contentlen) {
3718 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
3719 /* Commented by Albert 20120510 */
3720 /* Copy to the pwdinfo->p2p_peer_interface_addr. */
3721 /* So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
3722 /* #> iwpriv wlan0 p2p_get peer_ifa */
3723 /* After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
3724
3725 if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) {
3726 /* Re-invoke the persistent group. */
3727
3728 memset(&group_id, 0x00, sizeof(struct group_id_info));
3729 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
3730 if (attr_contentlen) {
3731 if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
3732 /* The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
3733 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
3734 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3735 status_code = P2P_STATUS_SUCCESS;
3736 } else {
3737 /* The p2p device sending this p2p invitation request wants to be the persistent GO. */
3738 if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) {
3739 u8 operatingch_info[5] = { 0x00 };
3740 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
3741 if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4])) {
3742 /* The operating channel is acceptable for this device. */
3743 pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4];
3744 pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
3745 _set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH);
3746 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
3747 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3748 status_code = P2P_STATUS_SUCCESS;
3749 } else {
3750 /* The operating channel isn't supported by this device. */
3751 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
3752 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3753 status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
3754 _set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
3755 }
3756 } else {
3757 /* Commented by Albert 20121130 */
3758 /* Intel will use the different P2P IE to store the operating channel information */
3759 /* Workaround for Intel WiDi 3.5 */
3760 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
3761 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3762 status_code = P2P_STATUS_SUCCESS;
3763 }
3764 } else {
3765 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
3766 status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
3767 }
3768 }
3769 } else {
3770 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3771 }
3772 } else {
3773 /* Received the invitation to join a P2P group. */
3774
3775 memset(&group_id, 0x00, sizeof(struct group_id_info));
3776 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
3777 if (attr_contentlen) {
3778 if (!memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
3779 /* In this case, the GO can't be myself. */
3780 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
3781 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3782 } else {
3783 /* The p2p device sending this p2p invitation request wants to join an existing P2P group */
3784 /* Commented by Albert 2012/06/28 */
3785 /* In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
3786 /* The peer device address should be the destination address for the provisioning discovery request. */
3787 /* Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
3788 /* The peer interface address should be the address for WPS mac address */
3789 memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr, ETH_ALEN);
3790 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3791 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
3792 status_code = P2P_STATUS_SUCCESS;
3793 }
3794 } else {
3795 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3796 }
3797 }
3798 } else {
3799 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
3800 }
3801
3802 pwdinfo->inviteresp_info.token = frame_body[7];
3803 issue_p2p_invitation_response(padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code);
3804 }
3805 break;
3806 case P2P_INVIT_RESP: {
3807 u8 attr_content = 0x00;
3808 u32 attr_contentlen = 0;
3809
3810 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3811 p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
3812 if (p2p_ie) {
3813 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
3814
3815 if (attr_contentlen == 1) {
3816 pwdinfo->invitereq_info.benable = false;
3817
3818 if (attr_content == P2P_STATUS_SUCCESS) {
3819 if (!memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) {
3820 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3821 } else {
3822 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3823 }
3824 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
3825 } else {
3826 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3827 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
3828 }
3829 } else {
3830 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3831 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
3832 }
3833 } else {
3834 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3835 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
3836 }
3837
3838 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL))
3839 _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3840 break;
3841 }
3842 case P2P_DEVDISC_REQ:
3843 process_p2p_devdisc_req(pwdinfo, pframe, len);
3844 break;
3845 case P2P_DEVDISC_RESP:
3846 process_p2p_devdisc_resp(pwdinfo, pframe, len);
3847 break;
3848 case P2P_PROVISION_DISC_REQ:
3849 process_p2p_provdisc_req(pwdinfo, pframe, len);
3850 memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
3851
3852 /* 20110902 Kurt */
3853 /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
3854 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
3855 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3856
3857 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
3858 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
3859 break;
3860 case P2P_PROVISION_DISC_RESP:
3861 /* Commented by Albert 20110707 */
3862 /* Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
3863 /* Commented by Albert 20110426 */
3864 /* The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
3865 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3866 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
3867 process_p2p_provdisc_resp(pwdinfo, pframe);
3868 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
3869 break;
3870 }
3871
3872 return _SUCCESS;
3873 }
3874
on_action_public_vendor(struct recv_frame * precv_frame)3875 static unsigned int on_action_public_vendor(struct recv_frame *precv_frame)
3876 {
3877 unsigned int ret = _FAIL;
3878 u8 *pframe = precv_frame->rx_data;
3879 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3880
3881 if (!memcmp(frame_body + 2, P2P_OUI, 4)) {
3882 ret = on_action_public_p2p(precv_frame);
3883 }
3884
3885 return ret;
3886 }
3887
on_action_public_default(struct recv_frame * precv_frame)3888 static unsigned int on_action_public_default(struct recv_frame *precv_frame)
3889 {
3890 unsigned int ret = _FAIL;
3891 u8 *pframe = precv_frame->rx_data;
3892 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3893 u8 token;
3894
3895 token = frame_body[2];
3896
3897 if (rtw_action_public_decache(precv_frame, token) == _FAIL)
3898 goto exit;
3899
3900 ret = _SUCCESS;
3901
3902 exit:
3903 return ret;
3904 }
3905
on_action_public(struct adapter * padapter,struct recv_frame * precv_frame)3906 unsigned int on_action_public(struct adapter *padapter, struct recv_frame *precv_frame)
3907 {
3908 unsigned int ret = _FAIL;
3909 u8 *pframe = precv_frame->rx_data;
3910 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
3911 u8 category, action;
3912
3913 /* check RA matches or not */
3914 if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))
3915 goto exit;
3916
3917 category = frame_body[0];
3918 if (category != WLAN_CATEGORY_PUBLIC)
3919 goto exit;
3920
3921 action = frame_body[1];
3922 switch (action) {
3923 case ACT_PUBLIC_VENDOR:
3924 ret = on_action_public_vendor(precv_frame);
3925 break;
3926 default:
3927 ret = on_action_public_default(precv_frame);
3928 break;
3929 }
3930
3931 exit:
3932 return ret;
3933 }
3934
OnAction_p2p(struct adapter * padapter,struct recv_frame * precv_frame)3935 unsigned int OnAction_p2p(struct adapter *padapter, struct recv_frame *precv_frame)
3936 {
3937 u8 *frame_body;
3938 u8 category, OUI_Subtype;
3939 u8 *pframe = precv_frame->rx_data;
3940 uint len = precv_frame->len;
3941 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3942
3943 /* check RA matches or not */
3944 if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
3945 return _SUCCESS;
3946
3947 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3948
3949 category = frame_body[0];
3950 if (category != RTW_WLAN_CATEGORY_P2P)
3951 return _SUCCESS;
3952
3953 if (be32_to_cpu(*((__be32 *)(frame_body + 1))) != P2POUI)
3954 return _SUCCESS;
3955
3956 len -= sizeof(struct ieee80211_hdr_3addr);
3957 OUI_Subtype = frame_body[5];
3958
3959 switch (OUI_Subtype) {
3960 case P2P_NOTICE_OF_ABSENCE:
3961 break;
3962 case P2P_PRESENCE_REQUEST:
3963 process_p2p_presence_req(pwdinfo, pframe, len);
3964 break;
3965 case P2P_PRESENCE_RESPONSE:
3966 break;
3967 case P2P_GO_DISC_REQUEST:
3968 break;
3969 default:
3970 break;
3971 }
3972 return _SUCCESS;
3973 }
3974
OnAction(struct adapter * padapter,struct recv_frame * precv_frame)3975 unsigned int OnAction(struct adapter *padapter, struct recv_frame *precv_frame)
3976 {
3977 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)precv_frame->rx_data;
3978
3979 switch (mgmt->u.action.category) {
3980 case WLAN_CATEGORY_BACK:
3981 OnAction_back(padapter, precv_frame);
3982 break;
3983 case WLAN_CATEGORY_PUBLIC:
3984 on_action_public(padapter, precv_frame);
3985 break;
3986 case RTW_WLAN_CATEGORY_P2P:
3987 OnAction_p2p(padapter, precv_frame);
3988 break;
3989 }
3990 return _SUCCESS;
3991 }
3992
alloc_mgtxmitframe(struct xmit_priv * pxmitpriv)3993 struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
3994 {
3995 struct xmit_frame *pmgntframe;
3996 struct xmit_buf *pxmitbuf;
3997
3998 pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
3999 if (!pmgntframe)
4000 return NULL;
4001
4002 pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
4003 if (!pxmitbuf) {
4004 rtw_free_xmitframe(pxmitpriv, pmgntframe);
4005 return NULL;
4006 }
4007 pmgntframe->frame_tag = MGNT_FRAMETAG;
4008 pmgntframe->pxmitbuf = pxmitbuf;
4009 pmgntframe->buf_addr = pxmitbuf->pbuf;
4010 pxmitbuf->priv_data = pmgntframe;
4011 return pmgntframe;
4012 }
4013
4014 /****************************************************************************
4015
4016 Following are some TX fuctions for WiFi MLME
4017
4018 *****************************************************************************/
4019
update_mgnt_tx_rate(struct adapter * padapter,u8 rate)4020 void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
4021 {
4022 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4023
4024 pmlmeext->tx_rate = rate;
4025 }
4026
update_mgntframe_attrib(struct adapter * padapter,struct pkt_attrib * pattrib)4027 void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
4028 {
4029 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4030
4031 memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
4032
4033 pattrib->hdrlen = 24;
4034 pattrib->nr_frags = 1;
4035 pattrib->priority = 7;
4036 pattrib->mac_id = 0;
4037 pattrib->qsel = 0x12;
4038
4039 pattrib->pktlen = 0;
4040
4041 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
4042 pattrib->raid = 6;/* b mode */
4043 else
4044 pattrib->raid = 5;/* a/g mode */
4045
4046 pattrib->encrypt = _NO_PRIVACY_;
4047 pattrib->bswenc = false;
4048
4049 pattrib->qos_en = false;
4050 pattrib->ht_en = false;
4051 pattrib->bwmode = HT_CHANNEL_WIDTH_20;
4052 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4053 pattrib->sgi = false;
4054
4055 pattrib->seqnum = pmlmeext->mgnt_seq;
4056
4057 pattrib->retry_ctrl = true;
4058 }
4059
dump_mgntframe(struct adapter * padapter,struct xmit_frame * pmgntframe)4060 void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
4061 {
4062 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4063 return;
4064
4065 rtl8188eu_mgnt_xmit(padapter, pmgntframe);
4066 }
4067
dump_mgntframe_and_wait(struct adapter * padapter,struct xmit_frame * pmgntframe,int timeout_ms)4068 s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
4069 {
4070 s32 ret = _FAIL;
4071 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
4072 struct submit_ctx sctx;
4073
4074 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4075 return ret;
4076
4077 rtw_sctx_init(&sctx, timeout_ms);
4078 pxmitbuf->sctx = &sctx;
4079
4080 ret = rtl8188eu_mgnt_xmit(padapter, pmgntframe);
4081
4082 if (ret == _SUCCESS)
4083 ret = rtw_sctx_wait(&sctx);
4084
4085 return ret;
4086 }
4087
dump_mgntframe_and_wait_ack(struct adapter * padapter,struct xmit_frame * pmgntframe)4088 s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
4089 {
4090 s32 ret = _FAIL;
4091 u32 timeout_ms = 500;/* 500ms */
4092 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4093
4094 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4095 return -1;
4096
4097 mutex_lock(&pxmitpriv->ack_tx_mutex);
4098 pxmitpriv->ack_tx = true;
4099
4100 pmgntframe->ack_report = 1;
4101 if (rtl8188eu_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
4102 ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
4103 }
4104
4105 pxmitpriv->ack_tx = false;
4106 mutex_unlock(&pxmitpriv->ack_tx_mutex);
4107
4108 return ret;
4109 }
4110
update_hidden_ssid(u8 * ies,u32 ies_len,u8 hidden_ssid_mode)4111 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
4112 {
4113 u8 *ssid_ie;
4114 int ssid_len_ori;
4115 int len_diff = 0;
4116
4117 ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
4118
4119 if (ssid_ie && ssid_len_ori > 0) {
4120 switch (hidden_ssid_mode) {
4121 case 1: {
4122 u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
4123 u32 remain_len = 0;
4124
4125 remain_len = ies_len - (next_ie - ies);
4126
4127 ssid_ie[1] = 0;
4128 memcpy(ssid_ie + 2, next_ie, remain_len);
4129 len_diff -= ssid_len_ori;
4130
4131 break;
4132 }
4133 case 2:
4134 memset(&ssid_ie[2], 0, ssid_len_ori);
4135 break;
4136 default:
4137 break;
4138 }
4139 }
4140
4141 return len_diff;
4142 }
4143
issue_beacon(struct adapter * padapter,int timeout_ms)4144 void issue_beacon(struct adapter *padapter, int timeout_ms)
4145 {
4146 struct xmit_frame *pmgntframe;
4147 struct pkt_attrib *pattrib;
4148 unsigned char *pframe;
4149 struct ieee80211_hdr *pwlanhdr;
4150 __le16 *fctrl;
4151 unsigned int rate_len;
4152 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4153 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4154 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4155 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4156 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
4157 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4158
4159 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4160 if (!pmgntframe)
4161 return;
4162 spin_lock_bh(&pmlmepriv->bcn_update_lock);
4163
4164 /* update attribute */
4165 pattrib = &pmgntframe->attrib;
4166 update_mgntframe_attrib(padapter, pattrib);
4167 pattrib->qsel = 0x10;
4168
4169 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4170
4171 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4172 pwlanhdr = (struct ieee80211_hdr *)pframe;
4173
4174 fctrl = &pwlanhdr->frame_control;
4175 *(fctrl) = 0;
4176
4177 eth_broadcast_addr(pwlanhdr->addr1);
4178 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
4179 memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
4180
4181 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
4182 /* pmlmeext->mgnt_seq++; */
4183 SetFrameSubType(pframe, WIFI_BEACON);
4184
4185 pframe += sizeof(struct ieee80211_hdr_3addr);
4186 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4187
4188 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
4189 /* for P2P : Primary Device Type & Device Name */
4190 u32 wpsielen = 0, insert_len = 0;
4191 u8 *wpsie = NULL;
4192 wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);
4193
4194 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {
4195 uint wps_offset, remainder_ielen;
4196 u8 *premainder_ie, *pframe_wscie;
4197
4198 wps_offset = (uint)(wpsie - cur_network->IEs);
4199 premainder_ie = wpsie + wpsielen;
4200 remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
4201 pframe_wscie = pframe + wps_offset;
4202 memcpy(pframe, cur_network->IEs, wps_offset + wpsielen);
4203 pframe += (wps_offset + wpsielen);
4204 pattrib->pktlen += (wps_offset + wpsielen);
4205
4206 /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
4207 /* Primary Device Type */
4208 /* Type: */
4209 *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
4210 insert_len += 2;
4211
4212 /* Length: */
4213 *(__be16 *)(pframe + insert_len) = cpu_to_be16(0x0008);
4214 insert_len += 2;
4215
4216 /* Value: */
4217 /* Category ID */
4218 *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
4219 insert_len += 2;
4220
4221 /* OUI */
4222 *(__be32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);
4223 insert_len += 4;
4224
4225 /* Sub Category ID */
4226 *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
4227 insert_len += 2;
4228
4229 /* Device Name */
4230 /* Type: */
4231 *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
4232 insert_len += 2;
4233
4234 /* Length: */
4235 *(__be16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);
4236 insert_len += 2;
4237
4238 /* Value: */
4239 memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);
4240 insert_len += pwdinfo->device_name_len;
4241
4242 /* update wsc ie length */
4243 *(pframe_wscie + 1) = (wpsielen - 2) + insert_len;
4244
4245 /* pframe move to end */
4246 pframe += insert_len;
4247 pattrib->pktlen += insert_len;
4248
4249 /* copy remainder_ie to pframe */
4250 memcpy(pframe, premainder_ie, remainder_ielen);
4251 pframe += remainder_ielen;
4252 pattrib->pktlen += remainder_ielen;
4253 } else {
4254 int len_diff;
4255 memcpy(pframe, cur_network->IEs, cur_network->IELength);
4256 len_diff = update_hidden_ssid(
4257 pframe + _BEACON_IE_OFFSET_
4258 , cur_network->IELength - _BEACON_IE_OFFSET_
4259 , pmlmeinfo->hidden_ssid_mode
4260 );
4261 pframe += (cur_network->IELength + len_diff);
4262 pattrib->pktlen += (cur_network->IELength + len_diff);
4263 }
4264
4265 {
4266 u8 *wps_ie;
4267 uint wps_ielen;
4268 u8 sr = 0;
4269 wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_,
4270 pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen);
4271 if (wps_ie && wps_ielen > 0)
4272 rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
4273 if (sr != 0)
4274 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
4275 else
4276 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
4277 }
4278
4279 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
4280 u32 len;
4281 len = build_beacon_p2p_ie(pwdinfo, pframe);
4282
4283 pframe += len;
4284 pattrib->pktlen += len;
4285 }
4286
4287 goto _issue_bcn;
4288 }
4289
4290 /* below for ad-hoc mode */
4291
4292 /* timestamp will be inserted by hardware */
4293 pframe += 8;
4294 pattrib->pktlen += 8;
4295
4296 /* beacon interval: 2 bytes */
4297
4298 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
4299
4300 pframe += 2;
4301 pattrib->pktlen += 2;
4302
4303 /* capability info: 2 bytes */
4304
4305 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
4306
4307 pframe += 2;
4308 pattrib->pktlen += 2;
4309
4310 /* SSID */
4311 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
4312
4313 /* supported rates... */
4314 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
4315 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
4316
4317 /* DS parameter set */
4318 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
4319
4320 {
4321 u8 erpinfo = 0;
4322 u32 ATIMWindow;
4323 /* IBSS Parameter Set... */
4324 ATIMWindow = 0;
4325 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
4326
4327 /* ERP IE */
4328 pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
4329 }
4330
4331 /* EXTERNDED SUPPORTED RATE */
4332 if (rate_len > 8)
4333 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
4334 /* todo:HT for adhoc */
4335 _issue_bcn:
4336
4337 pmlmepriv->update_bcn = false;
4338
4339 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
4340
4341 if ((pattrib->pktlen + TXDESC_SIZE) > 512)
4342 return;
4343
4344 pattrib->last_txcmdsz = pattrib->pktlen;
4345
4346 if (timeout_ms > 0)
4347 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
4348 else
4349 dump_mgntframe(padapter, pmgntframe);
4350 }
4351
issue_probersp(struct adapter * padapter,unsigned char * da,u8 is_valid_p2p_probereq)4352 void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
4353 {
4354 struct xmit_frame *pmgntframe;
4355 struct pkt_attrib *pattrib;
4356 unsigned char *pframe;
4357 struct ieee80211_hdr *pwlanhdr;
4358 __le16 *fctrl;
4359 unsigned char *mac, *bssid;
4360 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4361 u8 *pwps_ie;
4362 uint wps_ielen;
4363 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4364 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4365 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4366 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
4367 unsigned int rate_len;
4368 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4369
4370 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4371 if (!pmgntframe)
4372 return;
4373
4374 /* update attribute */
4375 pattrib = &pmgntframe->attrib;
4376 update_mgntframe_attrib(padapter, pattrib);
4377
4378 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4379
4380 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4381 pwlanhdr = (struct ieee80211_hdr *)pframe;
4382
4383 mac = myid(&padapter->eeprompriv);
4384 bssid = cur_network->MacAddress;
4385
4386 fctrl = &pwlanhdr->frame_control;
4387 *(fctrl) = 0;
4388 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4389 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4390 memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
4391
4392 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4393 pmlmeext->mgnt_seq++;
4394 SetFrameSubType(fctrl, WIFI_PROBERSP);
4395
4396 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
4397 pattrib->pktlen = pattrib->hdrlen;
4398 pframe += pattrib->hdrlen;
4399
4400 if (cur_network->IELength > MAX_IE_SZ)
4401 return;
4402
4403 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
4404 pwps_ie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
4405
4406 /* inerset & update wps_probe_resp_ie */
4407 if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
4408 uint wps_offset, remainder_ielen;
4409 u8 *premainder_ie;
4410
4411 wps_offset = (uint)(pwps_ie - cur_network->IEs);
4412
4413 premainder_ie = pwps_ie + wps_ielen;
4414
4415 remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
4416
4417 memcpy(pframe, cur_network->IEs, wps_offset);
4418 pframe += wps_offset;
4419 pattrib->pktlen += wps_offset;
4420
4421 wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
4422 if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) {
4423 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2);
4424 pframe += wps_ielen + 2;
4425 pattrib->pktlen += wps_ielen + 2;
4426 }
4427
4428 if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
4429 memcpy(pframe, premainder_ie, remainder_ielen);
4430 pframe += remainder_ielen;
4431 pattrib->pktlen += remainder_ielen;
4432 }
4433 } else {
4434 memcpy(pframe, cur_network->IEs, cur_network->IELength);
4435 pframe += cur_network->IELength;
4436 pattrib->pktlen += cur_network->IELength;
4437 }
4438 } else {
4439 /* timestamp will be inserted by hardware */
4440 pframe += 8;
4441 pattrib->pktlen += 8;
4442
4443 /* beacon interval: 2 bytes */
4444
4445 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
4446
4447 pframe += 2;
4448 pattrib->pktlen += 2;
4449
4450 /* capability info: 2 bytes */
4451
4452 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
4453
4454 pframe += 2;
4455 pattrib->pktlen += 2;
4456
4457 /* below for ad-hoc mode */
4458
4459 /* SSID */
4460 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
4461
4462 /* supported rates... */
4463 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
4464 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
4465
4466 /* DS parameter set */
4467 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
4468
4469 if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
4470 u8 erpinfo = 0;
4471 u32 ATIMWindow;
4472 /* IBSS Parameter Set... */
4473 /* ATIMWindow = cur->Configuration.ATIMWindow; */
4474 ATIMWindow = 0;
4475 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
4476
4477 /* ERP IE */
4478 pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
4479 }
4480
4481 /* EXTERNDED SUPPORTED RATE */
4482 if (rate_len > 8)
4483 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
4484 /* todo:HT for adhoc */
4485 }
4486
4487 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
4488 u32 len;
4489 len = build_probe_resp_p2p_ie(pwdinfo, pframe);
4490
4491 pframe += len;
4492 pattrib->pktlen += len;
4493 }
4494
4495 pattrib->last_txcmdsz = pattrib->pktlen;
4496
4497 dump_mgntframe(padapter, pmgntframe);
4498 }
4499
_issue_probereq(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da,int wait_ack)4500 static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, int wait_ack)
4501 {
4502 int ret = _FAIL;
4503 struct xmit_frame *pmgntframe;
4504 struct pkt_attrib *pattrib;
4505 unsigned char *pframe;
4506 struct ieee80211_hdr *pwlanhdr;
4507 __le16 *fctrl;
4508 unsigned char *mac;
4509 unsigned char bssrate[NumRates];
4510 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4511 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4512 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4513 int bssrate_len = 0;
4514
4515 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4516 if (!pmgntframe)
4517 goto exit;
4518
4519 /* update attribute */
4520 pattrib = &pmgntframe->attrib;
4521 update_mgntframe_attrib(padapter, pattrib);
4522
4523 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4524
4525 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4526 pwlanhdr = (struct ieee80211_hdr *)pframe;
4527
4528 mac = myid(&padapter->eeprompriv);
4529
4530 fctrl = &pwlanhdr->frame_control;
4531 *(fctrl) = 0;
4532
4533 if (da) {
4534 /* unicast probe request frame */
4535 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4536 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
4537 } else {
4538 /* broadcast probe request frame */
4539 eth_broadcast_addr(pwlanhdr->addr1);
4540 eth_broadcast_addr(pwlanhdr->addr3);
4541 }
4542
4543 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4544
4545 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4546 pmlmeext->mgnt_seq++;
4547 SetFrameSubType(pframe, WIFI_PROBEREQ);
4548
4549 pframe += sizeof(struct ieee80211_hdr_3addr);
4550 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4551
4552 if (pssid)
4553 pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &pattrib->pktlen);
4554 else
4555 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pattrib->pktlen);
4556
4557 get_rate_set(padapter, bssrate, &bssrate_len);
4558
4559 if (bssrate_len > 8) {
4560 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
4561 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
4562 } else {
4563 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
4564 }
4565
4566 /* add wps_ie for wps2.0 */
4567 if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
4568 memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
4569 pframe += pmlmepriv->wps_probe_req_ie_len;
4570 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4571 }
4572
4573 pattrib->last_txcmdsz = pattrib->pktlen;
4574
4575 if (wait_ack) {
4576 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
4577 } else {
4578 dump_mgntframe(padapter, pmgntframe);
4579 ret = _SUCCESS;
4580 }
4581
4582 exit:
4583 return ret;
4584 }
4585
issue_probereq(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da)4586 inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
4587 {
4588 _issue_probereq(padapter, pssid, da, false);
4589 }
4590
issue_probereq_ex(struct adapter * padapter,struct ndis_802_11_ssid * pssid,u8 * da,int try_cnt,int wait_ms)4591 int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da,
4592 int try_cnt, int wait_ms)
4593 {
4594 int ret;
4595 int i = 0;
4596
4597 do {
4598 ret = _issue_probereq(padapter, pssid, da, wait_ms > 0);
4599
4600 i++;
4601
4602 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
4603 break;
4604
4605 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
4606 msleep(wait_ms);
4607
4608 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
4609
4610 if (ret != _FAIL) {
4611 ret = _SUCCESS;
4612 goto exit;
4613 }
4614 exit:
4615 return ret;
4616 }
4617
4618 /* if psta == NULL, indiate we are station(client) now... */
issue_auth(struct adapter * padapter,struct sta_info * psta,unsigned short status)4619 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
4620 {
4621 struct xmit_frame *pmgntframe;
4622 struct pkt_attrib *pattrib;
4623 unsigned char *pframe;
4624 struct ieee80211_hdr *pwlanhdr;
4625 __le16 *fctrl;
4626 unsigned int val32;
4627 u16 val16;
4628 __le16 le_val16;
4629 int use_shared_key = 0;
4630 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4631 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4632 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4633
4634 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4635 if (!pmgntframe)
4636 return;
4637
4638 /* update attribute */
4639 pattrib = &pmgntframe->attrib;
4640 update_mgntframe_attrib(padapter, pattrib);
4641
4642 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4643
4644 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4645 pwlanhdr = (struct ieee80211_hdr *)pframe;
4646
4647 fctrl = &pwlanhdr->frame_control;
4648 *(fctrl) = 0;
4649
4650 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4651 pmlmeext->mgnt_seq++;
4652 SetFrameSubType(pframe, WIFI_AUTH);
4653
4654 pframe += sizeof(struct ieee80211_hdr_3addr);
4655 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4656
4657 if (psta) {/* for AP mode */
4658 memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
4659 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
4660 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
4661
4662 /* setting auth algo number */
4663 val16 = (u16)psta->authalg;
4664
4665 if (status != _STATS_SUCCESSFUL_)
4666 val16 = 0;
4667
4668 if (val16) {
4669 le_val16 = cpu_to_le16(val16);
4670 use_shared_key = 1;
4671 } else {
4672 le_val16 = 0;
4673 }
4674
4675 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_val16, &pattrib->pktlen);
4676
4677 /* setting auth seq number */
4678 val16 = (u16)psta->auth_seq;
4679 le_val16 = cpu_to_le16(val16);
4680 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_val16, &pattrib->pktlen);
4681
4682 /* setting status code... */
4683 val16 = status;
4684 le_val16 = cpu_to_le16(val16);
4685 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_val16, &pattrib->pktlen);
4686
4687 /* added challenging text... */
4688 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
4689 pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &pattrib->pktlen);
4690 } else {
4691 __le32 le_tmp32;
4692 __le16 le_tmp16;
4693 memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4694 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
4695 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4696
4697 /* setting auth algo number */
4698 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */
4699 if (val16)
4700 use_shared_key = 1;
4701
4702 /* setting IV for auth seq #3 */
4703 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
4704 val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
4705 le_tmp32 = cpu_to_le32(val32);
4706 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &pattrib->pktlen);
4707
4708 pattrib->iv_len = 4;
4709 }
4710
4711 le_tmp16 = cpu_to_le16(val16);
4712 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
4713
4714 /* setting auth seq number */
4715 val16 = pmlmeinfo->auth_seq;
4716 le_tmp16 = cpu_to_le16(val16);
4717 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
4718
4719 /* setting status code... */
4720 le_tmp16 = cpu_to_le16(status);
4721 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp16, &pattrib->pktlen);
4722
4723 /* then checking to see if sending challenging text... */
4724 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
4725 pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &pattrib->pktlen);
4726
4727 SetPrivacy(fctrl);
4728
4729 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
4730
4731 pattrib->encrypt = _WEP40_;
4732
4733 pattrib->icv_len = 4;
4734
4735 pattrib->pktlen += pattrib->icv_len;
4736 }
4737 }
4738
4739 pattrib->last_txcmdsz = pattrib->pktlen;
4740
4741 rtw_wep_encrypt(padapter, pmgntframe);
4742 dump_mgntframe(padapter, pmgntframe);
4743 }
4744
issue_asocrsp(struct adapter * padapter,unsigned short status,struct sta_info * pstat,int pkt_type)4745 void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
4746 {
4747 struct xmit_frame *pmgntframe;
4748 struct ieee80211_hdr *pwlanhdr;
4749 struct pkt_attrib *pattrib;
4750 unsigned char *pbuf, *pframe;
4751 unsigned short val;
4752 __le16 *fctrl;
4753 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4754 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4755 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4756 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4757 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4758 u8 *ie = pnetwork->IEs;
4759 __le16 lestatus, leval;
4760 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4761
4762 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4763 if (!pmgntframe)
4764 return;
4765
4766 /* update attribute */
4767 pattrib = &pmgntframe->attrib;
4768 update_mgntframe_attrib(padapter, pattrib);
4769
4770 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4771
4772 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4773 pwlanhdr = (struct ieee80211_hdr *)pframe;
4774
4775 fctrl = &pwlanhdr->frame_control;
4776 *(fctrl) = 0;
4777
4778 memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
4779 memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&padapter->eeprompriv), ETH_ALEN);
4780 memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4781
4782 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4783 pmlmeext->mgnt_seq++;
4784 if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
4785 SetFrameSubType(pwlanhdr, pkt_type);
4786 else
4787 return;
4788
4789 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
4790 pattrib->pktlen += pattrib->hdrlen;
4791 pframe += pattrib->hdrlen;
4792
4793 /* capability */
4794 val = *(unsigned short *)rtw_get_capability_from_ie(ie);
4795
4796 pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &pattrib->pktlen);
4797
4798 lestatus = cpu_to_le16(status);
4799 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &pattrib->pktlen);
4800
4801 leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
4802 pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&leval, &pattrib->pktlen);
4803
4804 if (pstat->bssratelen <= 8) {
4805 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &pattrib->pktlen);
4806 } else {
4807 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &pattrib->pktlen);
4808 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, pstat->bssratelen - 8, pstat->bssrateset + 8, &pattrib->pktlen);
4809 }
4810
4811 if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
4812 uint ie_len = 0;
4813
4814 /* FILL HT CAP INFO IE */
4815 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
4816 if (pbuf && ie_len > 0) {
4817 memcpy(pframe, pbuf, ie_len + 2);
4818 pframe += (ie_len + 2);
4819 pattrib->pktlen += (ie_len + 2);
4820 }
4821
4822 /* FILL HT ADD INFO IE */
4823 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
4824 if (pbuf && ie_len > 0) {
4825 memcpy(pframe, pbuf, ie_len + 2);
4826 pframe += (ie_len + 2);
4827 pattrib->pktlen += (ie_len + 2);
4828 }
4829 }
4830
4831 /* FILL WMM IE */
4832 if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
4833 uint ie_len = 0;
4834 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
4835
4836 for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
4837 pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
4838 if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
4839 memcpy(pframe, pbuf, ie_len + 2);
4840 pframe += (ie_len + 2);
4841 pattrib->pktlen += (ie_len + 2);
4842 break;
4843 }
4844
4845 if (!pbuf || ie_len == 0)
4846 break;
4847 }
4848 }
4849
4850 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
4851 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
4852
4853 /* add WPS IE ie for wps 2.0 */
4854 if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
4855 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
4856
4857 pframe += pmlmepriv->wps_assoc_resp_ie_len;
4858 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
4859 }
4860
4861 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device)) {
4862 u32 len;
4863
4864 len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
4865
4866 pframe += len;
4867 pattrib->pktlen += len;
4868 }
4869 pattrib->last_txcmdsz = pattrib->pktlen;
4870 dump_mgntframe(padapter, pmgntframe);
4871 }
4872
issue_assocreq(struct adapter * padapter)4873 void issue_assocreq(struct adapter *padapter)
4874 {
4875 int ret = _FAIL;
4876 struct xmit_frame *pmgntframe;
4877 struct pkt_attrib *pattrib;
4878 unsigned char *pframe, *p;
4879 struct ieee80211_hdr *pwlanhdr;
4880 __le16 *fctrl;
4881 __le16 le_tmp;
4882 unsigned int i, j, ie_len, index = 0;
4883 unsigned char bssrate[NumRates], sta_bssrate[NumRates];
4884 struct ndis_802_11_var_ie *pIE;
4885 struct registry_priv *pregpriv = &padapter->registrypriv;
4886 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4887 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4888 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4889 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4890 int bssrate_len = 0, sta_bssrate_len = 0;
4891 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4892 u8 p2pie[255] = { 0x00 };
4893 u16 p2pielen = 0;
4894
4895 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4896 if (!pmgntframe)
4897 goto exit;
4898
4899 /* update attribute */
4900 pattrib = &pmgntframe->attrib;
4901 update_mgntframe_attrib(padapter, pattrib);
4902
4903 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4904 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4905 pwlanhdr = (struct ieee80211_hdr *)pframe;
4906
4907 fctrl = &pwlanhdr->frame_control;
4908 *(fctrl) = 0;
4909 memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4910 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
4911 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
4912
4913 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4914 pmlmeext->mgnt_seq++;
4915 SetFrameSubType(pframe, WIFI_ASSOCREQ);
4916
4917 pframe += sizeof(struct ieee80211_hdr_3addr);
4918 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4919
4920 /* caps */
4921
4922 memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
4923
4924 pframe += 2;
4925 pattrib->pktlen += 2;
4926
4927 /* listen interval */
4928 /* todo: listen interval for power saving */
4929 le_tmp = cpu_to_le16(3);
4930 memcpy(pframe, (unsigned char *)&le_tmp, 2);
4931 pframe += 2;
4932 pattrib->pktlen += 2;
4933
4934 /* SSID */
4935 pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &pattrib->pktlen);
4936
4937 /* supported rate & extended supported rate */
4938
4939 /* Check if the AP's supported rates are also supported by STA. */
4940 get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
4941
4942 if (pmlmeext->cur_channel == 14)/* for JAPAN, channel 14 can only uses B Mode(CCK) */
4943 sta_bssrate_len = 4;
4944
4945 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
4946 if (pmlmeinfo->network.SupportedRates[i] == 0)
4947 break;
4948
4949 /* Check if the AP's supported rates are also supported by STA. */
4950 for (j = 0; j < sta_bssrate_len; j++) {
4951 /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
4952 if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)
4953 == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
4954 break;
4955 }
4956
4957 if (j != sta_bssrate_len)
4958 /* the rate is supported by STA */
4959 bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
4960 }
4961
4962 bssrate_len = index;
4963
4964 if (bssrate_len == 0) {
4965 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
4966 rtw_free_xmitframe(pxmitpriv, pmgntframe);
4967 goto exit; /* don't connect to AP if no joint supported rate */
4968 }
4969
4970 if (bssrate_len > 8) {
4971 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
4972 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
4973 } else {
4974 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
4975 }
4976
4977 /* RSN */
4978 p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
4979 if (p)
4980 pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, p + 2, &pattrib->pktlen);
4981
4982 /* HT caps */
4983 if (padapter->mlmepriv.htpriv.ht_option) {
4984 p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
4985 if (p && !is_ap_in_tkip(padapter)) {
4986 memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct HT_caps_element));
4987
4988 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
4989 if (pregpriv->cbw40_enable == 0)
4990 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
4991 else
4992 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1));
4993
4994 /* todo: disable SM power save mode */
4995 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c);
4996
4997 if (pregpriv->rx_stbc)
4998 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
4999 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16);
5000
5001 pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len, (u8 *)(&pmlmeinfo->HT_caps), &pattrib->pktlen);
5002 }
5003 }
5004
5005 /* vendor specific IE, such as WPA, WMM, WPS */
5006 for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
5007 pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
5008
5009 switch (pIE->ElementID) {
5010 case _VENDOR_SPECIFIC_IE_:
5011 if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
5012 (!memcmp(pIE->data, WMM_OUI, 4)) ||
5013 (!memcmp(pIE->data, WPS_OUI, 4))) {
5014 if (!padapter->registrypriv.wifi_spec) {
5015 /* Commented by Kurt 20110629 */
5016 /* In some older APs, WPS handshake */
5017 /* would be fail if we append vender extensions informations to AP */
5018 if (!memcmp(pIE->data, WPS_OUI, 4))
5019 pIE->Length = 14;
5020 }
5021 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &pattrib->pktlen);
5022 }
5023 break;
5024 default:
5025 break;
5026 }
5027 i += (pIE->Length + 2);
5028 }
5029
5030 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
5031 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
5032
5033 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
5034 /* Should add the P2P IE in the association request frame. */
5035 /* P2P OUI */
5036
5037 p2pielen = 0;
5038 p2pie[p2pielen++] = 0x50;
5039 p2pie[p2pielen++] = 0x6F;
5040 p2pie[p2pielen++] = 0x9A;
5041 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
5042
5043 /* Commented by Albert 20101109 */
5044 /* According to the P2P Specification, the association request frame should contain 3 P2P attributes */
5045 /* 1. P2P Capability */
5046 /* 2. Extended Listen Timing */
5047 /* 3. Device Info */
5048 /* Commented by Albert 20110516 */
5049 /* 4. P2P Interface */
5050
5051 /* P2P Capability */
5052 /* Type: */
5053 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
5054
5055 /* Length: */
5056 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
5057 p2pielen += 2;
5058
5059 /* Value: */
5060 /* Device Capability Bitmap, 1 byte */
5061 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
5062
5063 /* Group Capability Bitmap, 1 byte */
5064 if (pwdinfo->persistent_supported)
5065 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
5066 else
5067 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
5068
5069 /* Extended Listen Timing */
5070 /* Type: */
5071 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
5072
5073 /* Length: */
5074 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
5075 p2pielen += 2;
5076
5077 /* Value: */
5078 /* Availability Period */
5079 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
5080 p2pielen += 2;
5081
5082 /* Availability Interval */
5083 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
5084 p2pielen += 2;
5085
5086 /* Device Info */
5087 /* Type: */
5088 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
5089
5090 /* Length: */
5091 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
5092 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
5093 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
5094 p2pielen += 2;
5095
5096 /* Value: */
5097 /* P2P Device Address */
5098 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
5099 p2pielen += ETH_ALEN;
5100
5101 /* Config Method */
5102 /* This field should be big endian. Noted by P2P specification. */
5103 if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
5104 (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
5105 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
5106 else
5107 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC);
5108
5109 p2pielen += 2;
5110
5111 /* Primary Device Type */
5112 /* Category ID */
5113 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
5114 p2pielen += 2;
5115
5116 /* OUI */
5117 *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
5118 p2pielen += 4;
5119
5120 /* Sub Category ID */
5121 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
5122 p2pielen += 2;
5123
5124 /* Number of Secondary Device Types */
5125 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
5126
5127 /* Device Name */
5128 /* Type: */
5129 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
5130 p2pielen += 2;
5131
5132 /* Length: */
5133 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
5134 p2pielen += 2;
5135
5136 /* Value: */
5137 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
5138 p2pielen += pwdinfo->device_name_len;
5139
5140 /* P2P Interface */
5141 /* Type: */
5142 p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
5143
5144 /* Length: */
5145 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D);
5146 p2pielen += 2;
5147
5148 /* Value: */
5149 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Device Address */
5150 p2pielen += ETH_ALEN;
5151
5152 p2pie[p2pielen++] = 1; /* P2P Interface Address Count */
5153
5154 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Interface Address List */
5155 p2pielen += ETH_ALEN;
5156
5157 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
5158 }
5159
5160 pattrib->last_txcmdsz = pattrib->pktlen;
5161 dump_mgntframe(padapter, pmgntframe);
5162
5163 ret = _SUCCESS;
5164
5165 exit:
5166 if (ret == _SUCCESS)
5167 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
5168 else
5169 kfree(pmlmepriv->assoc_req);
5170 }
5171
5172 /* when wait_ack is ture, this function shoule be called at process context */
_issue_nulldata(struct adapter * padapter,unsigned char * da,unsigned int power_mode,int wait_ack)5173 static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
5174 {
5175 int ret = _FAIL;
5176 struct xmit_frame *pmgntframe;
5177 struct pkt_attrib *pattrib;
5178 unsigned char *pframe;
5179 struct ieee80211_hdr *pwlanhdr;
5180 __le16 *fctrl;
5181 struct xmit_priv *pxmitpriv;
5182 struct mlme_ext_priv *pmlmeext;
5183 struct mlme_ext_info *pmlmeinfo;
5184
5185 if (!padapter)
5186 goto exit;
5187
5188 pxmitpriv = &padapter->xmitpriv;
5189 pmlmeext = &padapter->mlmeextpriv;
5190 pmlmeinfo = &pmlmeext->mlmext_info;
5191
5192 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5193 if (!pmgntframe)
5194 goto exit;
5195
5196 /* update attribute */
5197 pattrib = &pmgntframe->attrib;
5198 update_mgntframe_attrib(padapter, pattrib);
5199 pattrib->retry_ctrl = false;
5200
5201 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5202
5203 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5204 pwlanhdr = (struct ieee80211_hdr *)pframe;
5205
5206 fctrl = &pwlanhdr->frame_control;
5207 *(fctrl) = 0;
5208
5209 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
5210 SetFrDs(fctrl);
5211 else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
5212 SetToDs(fctrl);
5213
5214 if (power_mode)
5215 SetPwrMgt(fctrl);
5216
5217 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5218 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5219 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5220
5221 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5222 pmlmeext->mgnt_seq++;
5223 SetFrameSubType(pframe, WIFI_DATA_NULL);
5224
5225 pframe += sizeof(struct ieee80211_hdr_3addr);
5226 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
5227
5228 pattrib->last_txcmdsz = pattrib->pktlen;
5229
5230 if (wait_ack) {
5231 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5232 } else {
5233 dump_mgntframe(padapter, pmgntframe);
5234 ret = _SUCCESS;
5235 }
5236
5237 exit:
5238 return ret;
5239 }
5240
5241 /* when wait_ms > 0 , this function shoule be called at process context */
5242 /* da == NULL for station mode */
issue_nulldata(struct adapter * padapter,unsigned char * da,unsigned int power_mode,int try_cnt,int wait_ms)5243 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
5244 {
5245 int ret;
5246 int i = 0;
5247 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5248 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5249
5250 /* da == NULL, assum it's null data for sta to ap*/
5251 if (!da)
5252 da = get_my_bssid(&pmlmeinfo->network);
5253
5254 do {
5255 ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
5256
5257 i++;
5258
5259 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5260 break;
5261
5262 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5263 msleep(wait_ms);
5264 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5265
5266 if (ret != _FAIL) {
5267 ret = _SUCCESS;
5268 goto exit;
5269 }
5270 exit:
5271 return ret;
5272 }
5273
5274 /* when wait_ack is ture, this function shoule be called at process context */
_issue_qos_nulldata(struct adapter * padapter,unsigned char * da,u16 tid,int wait_ack)5275 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
5276 {
5277 int ret = _FAIL;
5278 struct xmit_frame *pmgntframe;
5279 struct pkt_attrib *pattrib;
5280 unsigned char *pframe;
5281 struct ieee80211_hdr *pwlanhdr;
5282 __le16 *fctrl;
5283 unsigned short *qc;
5284 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5285 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5286 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5287
5288 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5289 if (!pmgntframe)
5290 goto exit;
5291
5292 /* update attribute */
5293 pattrib = &pmgntframe->attrib;
5294 update_mgntframe_attrib(padapter, pattrib);
5295
5296 pattrib->hdrlen += 2;
5297 pattrib->qos_en = true;
5298 pattrib->eosp = 1;
5299 pattrib->ack_policy = 0;
5300 pattrib->mdata = 0;
5301
5302 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5303
5304 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5305 pwlanhdr = (struct ieee80211_hdr *)pframe;
5306
5307 fctrl = &pwlanhdr->frame_control;
5308 *(fctrl) = 0;
5309
5310 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
5311 SetFrDs(fctrl);
5312 else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
5313 SetToDs(fctrl);
5314
5315 qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
5316
5317 SetPriority(qc, tid);
5318
5319 SetEOSP(qc, pattrib->eosp);
5320
5321 SetAckpolicy(qc, pattrib->ack_policy);
5322
5323 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5324 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5325 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5326
5327 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5328 pmlmeext->mgnt_seq++;
5329 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
5330
5331 pframe += sizeof(struct ieee80211_qos_hdr);
5332 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
5333
5334 pattrib->last_txcmdsz = pattrib->pktlen;
5335
5336 if (wait_ack) {
5337 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5338 } else {
5339 dump_mgntframe(padapter, pmgntframe);
5340 ret = _SUCCESS;
5341 }
5342
5343 exit:
5344 return ret;
5345 }
5346
5347 /* when wait_ms > 0 , this function shoule be called at process context */
5348 /* da == NULL for station mode */
issue_qos_nulldata(struct adapter * padapter,unsigned char * da,u16 tid,int try_cnt,int wait_ms)5349 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
5350 {
5351 int ret;
5352 int i = 0;
5353 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5354 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5355
5356 /* da == NULL, assum it's null data for sta to ap*/
5357 if (!da)
5358 da = get_my_bssid(&pmlmeinfo->network);
5359
5360 do {
5361 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
5362
5363 i++;
5364
5365 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5366 break;
5367
5368 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5369 msleep(wait_ms);
5370 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5371
5372 if (ret != _FAIL) {
5373 ret = _SUCCESS;
5374 goto exit;
5375 }
5376 exit:
5377 return ret;
5378 }
5379
_issue_deauth(struct adapter * padapter,unsigned char * da,unsigned short reason,u8 wait_ack)5380 static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
5381 {
5382 struct xmit_frame *pmgntframe;
5383 struct pkt_attrib *pattrib;
5384 unsigned char *pframe;
5385 struct ieee80211_hdr *pwlanhdr;
5386 __le16 *fctrl;
5387 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5388 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5389 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5390 int ret = _FAIL;
5391 __le16 le_tmp;
5392 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
5393
5394 if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
5395 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
5396 _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
5397 }
5398
5399 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5400 if (!pmgntframe)
5401 goto exit;
5402
5403 /* update attribute */
5404 pattrib = &pmgntframe->attrib;
5405 update_mgntframe_attrib(padapter, pattrib);
5406 pattrib->retry_ctrl = false;
5407
5408 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5409
5410 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5411 pwlanhdr = (struct ieee80211_hdr *)pframe;
5412
5413 fctrl = &pwlanhdr->frame_control;
5414 *(fctrl) = 0;
5415
5416 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5417 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5418 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5419
5420 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5421 pmlmeext->mgnt_seq++;
5422 SetFrameSubType(pframe, WIFI_DEAUTH);
5423
5424 pframe += sizeof(struct ieee80211_hdr_3addr);
5425 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
5426
5427 le_tmp = cpu_to_le16(reason);
5428 pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &pattrib->pktlen);
5429
5430 pattrib->last_txcmdsz = pattrib->pktlen;
5431
5432 if (wait_ack) {
5433 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5434 } else {
5435 dump_mgntframe(padapter, pmgntframe);
5436 ret = _SUCCESS;
5437 }
5438
5439 exit:
5440 return ret;
5441 }
5442
issue_deauth(struct adapter * padapter,unsigned char * da,unsigned short reason)5443 int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
5444 {
5445 return _issue_deauth(padapter, da, reason, false);
5446 }
5447
issue_deauth_ex(struct adapter * padapter,u8 * da,unsigned short reason,int try_cnt,int wait_ms)5448 int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
5449 int wait_ms)
5450 {
5451 int ret;
5452 int i = 0;
5453
5454 do {
5455 ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
5456
5457 i++;
5458
5459 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5460 break;
5461
5462 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5463 msleep(wait_ms);
5464 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5465
5466 if (ret != _FAIL) {
5467 ret = _SUCCESS;
5468 goto exit;
5469 }
5470 exit:
5471 return ret;
5472 }
5473
issue_action_BA(struct adapter * padapter,unsigned char * raddr,u8 action,u16 status)5474 void issue_action_BA(struct adapter *padapter, unsigned char *raddr, u8 action, u16 status)
5475 {
5476 u16 start_seq;
5477 u16 BA_starting_seqctrl = 0;
5478 struct xmit_frame *pmgntframe;
5479 struct pkt_attrib *pattrib;
5480 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5481 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5482 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5483 struct sta_info *psta;
5484 struct sta_priv *pstapriv = &padapter->stapriv;
5485 struct registry_priv *pregpriv = &padapter->registrypriv;
5486 struct ieee80211_mgmt *mgmt;
5487 u16 capab, params;
5488
5489 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5490 if (!pmgntframe)
5491 return;
5492
5493 /* update attribute */
5494 pattrib = &pmgntframe->attrib;
5495 update_mgntframe_attrib(padapter, pattrib);
5496
5497 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5498
5499 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
5500
5501 mgmt->frame_control = cpu_to_le16(IEEE80211_STYPE_ACTION | IEEE80211_FTYPE_MGMT);
5502
5503 memcpy(mgmt->da, raddr, ETH_ALEN);
5504 memcpy(mgmt->sa, myid(&padapter->eeprompriv), ETH_ALEN);
5505 memcpy(mgmt->bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5506
5507 mgmt->seq_ctrl = cpu_to_le16(pmlmeext->mgnt_seq);
5508 pmlmeext->mgnt_seq++;
5509
5510 mgmt->u.action.category = WLAN_CATEGORY_BACK;
5511
5512 switch (action) {
5513 case WLAN_ACTION_ADDBA_REQ:
5514 mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
5515 do {
5516 pmlmeinfo->dialogToken++;
5517 } while (pmlmeinfo->dialogToken == 0);
5518 mgmt->u.action.u.addba_req.dialog_token = pmlmeinfo->dialogToken;
5519
5520 /* immediate ack & 64 buffer size */
5521 capab = u16_encode_bits(64, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
5522 capab |= u16_encode_bits(1, IEEE80211_ADDBA_PARAM_POLICY_MASK);
5523 capab |= u16_encode_bits(status, IEEE80211_ADDBA_PARAM_TID_MASK);
5524 mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
5525
5526 mgmt->u.action.u.addba_req.timeout = cpu_to_le16(5000); /* 5 ms */
5527
5528 psta = rtw_get_stainfo(pstapriv, raddr);
5529 if (psta) {
5530 start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] & 0xfff) + 1;
5531
5532 psta->BA_starting_seqctrl[status & 0x07] = start_seq;
5533
5534 BA_starting_seqctrl = start_seq << 4;
5535 }
5536 mgmt->u.action.u.addba_req.start_seq_num = cpu_to_le16(BA_starting_seqctrl);
5537
5538 pattrib->pktlen = offsetofend(struct ieee80211_mgmt,
5539 u.action.u.addba_req.start_seq_num);
5540 break;
5541 case WLAN_ACTION_ADDBA_RESP:
5542 mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
5543 mgmt->u.action.u.addba_resp.dialog_token = pmlmeinfo->ADDBA_req.dialog_token;
5544 mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
5545 capab = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
5546 capab |= u16_encode_bits(64, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
5547 capab |= u16_encode_bits(pregpriv->ampdu_amsdu, IEEE80211_ADDBA_PARAM_AMSDU_MASK);
5548 mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
5549 mgmt->u.action.u.addba_resp.timeout = pmlmeinfo->ADDBA_req.BA_timeout_value;
5550 pattrib->pktlen = offsetofend(struct ieee80211_mgmt, u.action.u.addba_resp.timeout);
5551 break;
5552 case WLAN_ACTION_DELBA:
5553 mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
5554 mgmt->u.action.u.delba.params = cpu_to_le16((status & 0x1F) << 3);
5555 params = u16_encode_bits((status & 0x1), IEEE80211_DELBA_PARAM_INITIATOR_MASK);
5556 params |= u16_encode_bits((status >> 1) & 0xF, IEEE80211_DELBA_PARAM_TID_MASK);
5557 mgmt->u.action.u.delba.params = cpu_to_le16(params);
5558 mgmt->u.action.u.delba.reason_code = cpu_to_le16(WLAN_STATUS_REQUEST_DECLINED);
5559 pattrib->pktlen = offsetofend(struct ieee80211_mgmt, u.action.u.delba.reason_code);
5560 break;
5561 default:
5562 break;
5563 }
5564
5565 pattrib->last_txcmdsz = pattrib->pktlen;
5566
5567 dump_mgntframe(padapter, pmgntframe);
5568 }
5569
issue_action_BSSCoexistPacket(struct adapter * padapter)5570 static void issue_action_BSSCoexistPacket(struct adapter *padapter)
5571 {
5572 struct list_head *plist, *phead;
5573 unsigned char category, action;
5574 struct xmit_frame *pmgntframe;
5575 struct pkt_attrib *pattrib;
5576 unsigned char *pframe;
5577 struct ieee80211_hdr *pwlanhdr;
5578 __le16 *fctrl;
5579 struct wlan_network *pnetwork = NULL;
5580 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5581 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5582 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5583 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5584 struct __queue *queue = &pmlmepriv->scanned_queue;
5585 u8 InfoContent[16] = {0};
5586 u8 ICS[8][15];
5587 if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
5588 return;
5589
5590 if (pmlmeinfo->bwmode_updated)
5591 return;
5592
5593 category = WLAN_CATEGORY_PUBLIC;
5594 action = ACT_PUBLIC_BSSCOEXIST;
5595
5596 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5597 if (!pmgntframe)
5598 return;
5599
5600 /* update attribute */
5601 pattrib = &pmgntframe->attrib;
5602 update_mgntframe_attrib(padapter, pattrib);
5603
5604 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5605
5606 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5607 pwlanhdr = (struct ieee80211_hdr *)pframe;
5608
5609 fctrl = &pwlanhdr->frame_control;
5610 *(fctrl) = 0;
5611
5612 memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5613 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5614 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5615
5616 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5617 pmlmeext->mgnt_seq++;
5618 SetFrameSubType(pframe, WIFI_ACTION);
5619
5620 pframe += sizeof(struct ieee80211_hdr_3addr);
5621 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
5622
5623 pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
5624 pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
5625
5626 /* */
5627 if (pmlmepriv->num_FortyMHzIntolerant > 0) {
5628 u8 iedata = 0;
5629
5630 iedata |= BIT(2);/* 20 MHz BSS Width Request */
5631
5632 pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &pattrib->pktlen);
5633 }
5634
5635 /* */
5636 memset(ICS, 0, sizeof(ICS));
5637 if (pmlmepriv->num_sta_no_ht > 0) {
5638 int i;
5639
5640 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
5641
5642 phead = get_list_head(queue);
5643 plist = phead->next;
5644
5645 while (phead != plist) {
5646 int len;
5647 u8 *p;
5648 struct wlan_bssid_ex *pbss_network;
5649
5650 pnetwork = container_of(plist, struct wlan_network, list);
5651
5652 plist = plist->next;
5653
5654 pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
5655
5656 p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
5657 if (!p || len == 0) { /* non-HT */
5658 if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
5659 continue;
5660
5661 ICS[0][pbss_network->Configuration.DSConfig] = 1;
5662
5663 if (ICS[0][0] == 0)
5664 ICS[0][0] = 1;
5665 }
5666 }
5667 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
5668
5669 for (i = 0; i < 8; i++) {
5670 if (ICS[i][0] == 1) {
5671 int j, k = 0;
5672
5673 InfoContent[k] = i;
5674 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
5675 k++;
5676
5677 for (j = 1; j <= 14; j++) {
5678 if (ICS[i][j] == 1) {
5679 if (k < 16) {
5680 InfoContent[k] = j; /* channel number */
5681 /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
5682 k++;
5683 }
5684 }
5685 }
5686
5687 pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &pattrib->pktlen);
5688 }
5689 }
5690 }
5691
5692 pattrib->last_txcmdsz = pattrib->pktlen;
5693
5694 dump_mgntframe(padapter, pmgntframe);
5695 }
5696
send_delba(struct adapter * padapter,u8 initiator,u8 * addr)5697 unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
5698 {
5699 struct sta_priv *pstapriv = &padapter->stapriv;
5700 struct sta_info *psta = NULL;
5701 /* struct recv_reorder_ctrl *preorder_ctrl; */
5702 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5703 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5704 u16 tid;
5705
5706 if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
5707 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
5708 return _SUCCESS;
5709
5710 psta = rtw_get_stainfo(pstapriv, addr);
5711 if (!psta)
5712 return _SUCCESS;
5713
5714 if (initiator == 0) { /* recipient */
5715 for (tid = 0; tid < MAXTID; tid++) {
5716 if (psta->recvreorder_ctrl[tid].enable) {
5717 issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
5718 psta->recvreorder_ctrl[tid].enable = false;
5719 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
5720 }
5721 }
5722 } else if (initiator == 1) { /* originator */
5723 for (tid = 0; tid < MAXTID; tid++) {
5724 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
5725 issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
5726 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
5727 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
5728 }
5729 }
5730 }
5731
5732 return _SUCCESS;
5733 }
5734
send_beacon(struct adapter * padapter)5735 unsigned int send_beacon(struct adapter *padapter)
5736 {
5737 bool bxmitok = false;
5738 int issue = 0;
5739 int poll = 0;
5740
5741 clear_beacon_valid_bit(padapter);
5742
5743 do {
5744 issue_beacon(padapter, 100);
5745 issue++;
5746 do {
5747 yield();
5748 bxmitok = get_beacon_valid_bit(padapter);
5749 poll++;
5750 } while ((poll % 10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
5751 } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
5752
5753 if (padapter->bSurpriseRemoved || padapter->bDriverStopped || !bxmitok)
5754 return _FAIL;
5755
5756 return _SUCCESS;
5757 }
5758
get_beacon_valid_bit(struct adapter * adapter)5759 bool get_beacon_valid_bit(struct adapter *adapter)
5760 {
5761 int res;
5762 u8 reg;
5763
5764 res = rtw_read8(adapter, REG_TDECTRL + 2, ®);
5765 if (res)
5766 return false;
5767
5768 /* BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2 */
5769 return BIT(0) & reg;
5770 }
5771
clear_beacon_valid_bit(struct adapter * adapter)5772 void clear_beacon_valid_bit(struct adapter *adapter)
5773 {
5774 int res;
5775 u8 reg;
5776
5777 res = rtw_read8(adapter, REG_TDECTRL + 2, ®);
5778 if (res)
5779 return;
5780
5781 /* BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
5782 rtw_write8(adapter, REG_TDECTRL + 2, reg | BIT(0));
5783 }
5784
rtw_resume_tx_beacon(struct adapter * adapt)5785 void rtw_resume_tx_beacon(struct adapter *adapt)
5786 {
5787 struct hal_data_8188e *haldata = &adapt->haldata;
5788
5789 /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
5790 /* which should be read from register to a global variable. */
5791
5792 rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6));
5793 haldata->RegFwHwTxQCtrl |= BIT(6);
5794 rtw_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff);
5795 haldata->RegReg542 |= BIT(0);
5796 rtw_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
5797 }
5798
rtw_stop_tx_beacon(struct adapter * adapt)5799 void rtw_stop_tx_beacon(struct adapter *adapt)
5800 {
5801 struct hal_data_8188e *haldata = &adapt->haldata;
5802
5803 /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
5804 /* which should be read from register to a global variable. */
5805
5806 rtw_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6)));
5807 haldata->RegFwHwTxQCtrl &= (~BIT(6));
5808 rtw_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64);
5809 haldata->RegReg542 &= ~(BIT(0));
5810 rtw_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
5811
5812 /* todo: CheckFwRsvdPageContent(Adapter); 2010.06.23. Added by tynli. */
5813 }
5814
rtw_set_opmode(struct adapter * adapter,u8 mode)5815 static void rtw_set_opmode(struct adapter *adapter, u8 mode)
5816 {
5817 u8 val8;
5818 int res;
5819
5820 /* disable Port0 TSF update */
5821 res = rtw_read8(adapter, REG_BCN_CTRL, &val8);
5822 if (res)
5823 return;
5824
5825 rtw_write8(adapter, REG_BCN_CTRL, val8 | BIT(4));
5826
5827 /* set net_type */
5828 res = rtw_read8(adapter, MSR, &val8);
5829 if (res)
5830 return;
5831
5832 val8 &= 0x0c;
5833 val8 |= mode;
5834 rtw_write8(adapter, MSR, val8);
5835
5836 if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
5837 rtw_stop_tx_beacon(adapter);
5838
5839 rtw_write8(adapter, REG_BCN_CTRL, 0x19);/* disable atim wnd */
5840 } else if (mode == _HW_STATE_ADHOC_) {
5841 rtw_resume_tx_beacon(adapter);
5842 rtw_write8(adapter, REG_BCN_CTRL, 0x1a);
5843 } else if (mode == _HW_STATE_AP_) {
5844 rtw_resume_tx_beacon(adapter);
5845
5846 rtw_write8(adapter, REG_BCN_CTRL, 0x12);
5847
5848 /* Set RCR */
5849 rtw_write32(adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */
5850 /* enable to rx data frame */
5851 rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
5852 /* enable to rx ps-poll */
5853 rtw_write16(adapter, REG_RXFLTMAP1, 0x0400);
5854
5855 /* Beacon Control related register for first time */
5856 rtw_write8(adapter, REG_BCNDMATIM, 0x02); /* 2ms */
5857
5858 rtw_write8(adapter, REG_ATIMWND, 0x0a); /* 10ms */
5859 rtw_write16(adapter, REG_BCNTCFG, 0x00);
5860 rtw_write16(adapter, REG_TBTT_PROHIBIT, 0xff04);
5861 rtw_write16(adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */
5862
5863 /* reset TSF */
5864 rtw_write8(adapter, REG_DUAL_TSF_RST, BIT(0));
5865
5866 /* BIT(3) - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */
5867 res = rtw_read8(adapter, REG_MBID_NUM, &val8);
5868 if (res)
5869 return;
5870
5871 rtw_write8(adapter, REG_MBID_NUM, val8 | BIT(3) | BIT(4));
5872
5873 /* enable BCN0 Function for if1 */
5874 /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
5875 rtw_write8(adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1)));
5876
5877 /* dis BCN1 ATIM WND if if2 is station */
5878 res = rtw_read8(adapter, REG_BCN_CTRL_1, &val8);
5879 if (res)
5880 return;
5881
5882 rtw_write8(adapter, REG_BCN_CTRL_1, val8 | BIT(0));
5883 }
5884 }
5885
5886 /****************************************************************************
5887
5888 Following are some utitity fuctions for WiFi MLME
5889
5890 *****************************************************************************/
5891
rtw_set_initial_gain(struct adapter * adapter,u8 gain)5892 static void rtw_set_initial_gain(struct adapter *adapter, u8 gain)
5893 {
5894 struct hal_data_8188e *haldata = &adapter->haldata;
5895 struct odm_dm_struct *odmpriv = &haldata->odmpriv;
5896 struct rtw_dig *digtable = &odmpriv->DM_DigTable;
5897
5898 if (gain == 0xff) {
5899 /* restore rx gain */
5900 ODM_Write_DIG(odmpriv, digtable->BackupIGValue);
5901 } else {
5902 digtable->BackupIGValue = digtable->CurIGValue;
5903 ODM_Write_DIG(odmpriv, gain);
5904 }
5905 }
5906
rtw_mlme_under_site_survey(struct adapter * adapter)5907 void rtw_mlme_under_site_survey(struct adapter *adapter)
5908 {
5909 /* config RCR to receive different BSSID & not to receive data frame */
5910
5911 int res;
5912 u8 reg;
5913 u32 v;
5914
5915 res = rtw_read32(adapter, REG_RCR, &v);
5916 if (res)
5917 return;
5918
5919 v &= ~(RCR_CBSSID_BCN);
5920 rtw_write32(adapter, REG_RCR, v);
5921 /* reject all data frame */
5922 rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
5923
5924 /* disable update TSF */
5925 res = rtw_read8(adapter, REG_BCN_CTRL, ®);
5926 if (res)
5927 return;
5928
5929 rtw_write8(adapter, REG_BCN_CTRL, reg | BIT(4));
5930 }
5931
rtw_mlme_site_survey_done(struct adapter * adapter)5932 void rtw_mlme_site_survey_done(struct adapter *adapter)
5933 {
5934 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
5935 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5936 u32 reg32;
5937 int res;
5938 u8 reg;
5939
5940 if ((is_client_associated_to_ap(adapter)) ||
5941 ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {
5942 /* enable to rx data frame */
5943 rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
5944
5945 /* enable update TSF */
5946 res = rtw_read8(adapter, REG_BCN_CTRL, ®);
5947 if (res)
5948 return;
5949
5950 rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4)));
5951 } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
5952 rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
5953 /* enable update TSF */
5954 res = rtw_read8(adapter, REG_BCN_CTRL, ®);
5955 if (res)
5956 return;
5957
5958 rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4)));
5959 }
5960
5961 res = rtw_read32(adapter, REG_RCR, ®32);
5962 if (res)
5963 return;
5964
5965 rtw_write32(adapter, REG_RCR, reg32 | RCR_CBSSID_BCN);
5966 }
5967
site_survey(struct adapter * padapter)5968 void site_survey(struct adapter *padapter)
5969 {
5970 unsigned char survey_channel = 0;
5971 enum rt_scan_type ScanType = SCAN_PASSIVE;
5972 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5973 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5974 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
5975
5976 if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
5977 if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
5978 survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
5979 } else {
5980 survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
5981 }
5982 ScanType = SCAN_ACTIVE;
5983 } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
5984 /* Commented by Albert 2011/06/03 */
5985 /* The driver is in the find phase, it should go through the social channel. */
5986 int ch_set_idx;
5987 survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
5988 ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
5989 if (ch_set_idx >= 0)
5990 ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
5991 else
5992 ScanType = SCAN_ACTIVE;
5993 } else {
5994 struct rtw_ieee80211_channel *ch;
5995 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
5996 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
5997 survey_channel = ch->hw_value;
5998 ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
5999 }
6000 }
6001
6002 if (survey_channel != 0) {
6003 if (pmlmeext->sitesurvey_res.channel_idx == 0)
6004 set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6005 else
6006 SelectChannel(padapter, survey_channel);
6007
6008 if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
6009 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
6010 rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
6011 issue_probereq_p2p(padapter, NULL);
6012 issue_probereq_p2p(padapter, NULL);
6013 issue_probereq_p2p(padapter, NULL);
6014 } else {
6015 int i;
6016 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
6017 if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
6018 /* todo: to issue two probe req??? */
6019 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
6020 /* msleep(SURVEY_TO>>1); */
6021 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
6022 }
6023 }
6024
6025 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
6026 /* todo: to issue two probe req??? */
6027 issue_probereq(padapter, NULL, NULL);
6028 /* msleep(SURVEY_TO>>1); */
6029 issue_probereq(padapter, NULL, NULL);
6030 }
6031 }
6032 }
6033
6034 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
6035 } else {
6036 /* channel number is 0 or this channel is not valid. */
6037 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
6038 if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
6039 /* Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
6040 /* This will let the following flow to run the scanning end. */
6041 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
6042 }
6043 }
6044
6045 if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
6046 /* Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
6047 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6048 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
6049 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
6050
6051 /* restore RX GAIN */
6052 rtw_set_initial_gain(padapter, 0xff);
6053 /* turn on dynamic functions */
6054 Restore_DM_Func_Flag(padapter);
6055 /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
6056
6057 _set_timer(&pwdinfo->find_phase_timer, (u32)((u32)(pwdinfo->listen_dwell) * 100));
6058 } else {
6059 /* 20100721:Interrupt scan operation here. */
6060 /* For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
6061 /* It compares the scan result and select beter one to do connection. */
6062 if (AntDivBeforeLink8188E(padapter)) {
6063 pmlmeext->sitesurvey_res.bss_cnt = 0;
6064 pmlmeext->sitesurvey_res.channel_idx = -1;
6065 pmlmeext->chan_scan_time = SURVEY_TO / 2;
6066 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
6067 return;
6068 }
6069 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
6070 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
6071 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
6072
6073 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
6074
6075 /* switch back to the original channel */
6076
6077 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
6078 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6079 else
6080 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6081
6082 /* config MSR */
6083 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
6084
6085 /* restore RX GAIN */
6086 rtw_set_initial_gain(padapter, 0xff);
6087 /* turn on dynamic functions */
6088 Restore_DM_Func_Flag(padapter);
6089 /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
6090
6091 if (is_client_associated_to_ap(padapter))
6092 issue_nulldata(padapter, NULL, 0, 3, 500);
6093
6094 rtw_mlme_site_survey_done(padapter);
6095
6096 report_surveydone_event(padapter);
6097
6098 pmlmeext->chan_scan_time = SURVEY_TO;
6099 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
6100
6101 issue_action_BSSCoexistPacket(padapter);
6102 issue_action_BSSCoexistPacket(padapter);
6103 issue_action_BSSCoexistPacket(padapter);
6104 }
6105 }
6106 }
6107
6108 /* collect bss info from Beacon and Probe request/response frames. */
collect_bss_info(struct adapter * padapter,struct recv_frame * precv_frame,struct wlan_bssid_ex * bssid)6109 u8 collect_bss_info(struct adapter *padapter, struct recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
6110 {
6111 int i;
6112 u32 len;
6113 u8 *p;
6114 u16 val16, subtype;
6115 u8 *pframe = precv_frame->rx_data;
6116 u32 packet_len = precv_frame->len;
6117 u8 ie_offset;
6118 struct registry_priv *pregistrypriv = &padapter->registrypriv;
6119 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6120 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6121 __le32 le32_tmp;
6122
6123 len = packet_len - sizeof(struct ieee80211_hdr_3addr);
6124
6125 if (len > MAX_IE_SZ)
6126 return _FAIL;
6127
6128 memset(bssid, 0, sizeof(struct wlan_bssid_ex));
6129
6130 subtype = GetFrameSubType(pframe);
6131
6132 if (subtype == WIFI_BEACON) {
6133 bssid->Reserved[0] = 1;
6134 ie_offset = _BEACON_IE_OFFSET_;
6135 } else {
6136 /* FIXME : more type */
6137 if (subtype == WIFI_PROBEREQ) {
6138 ie_offset = _PROBEREQ_IE_OFFSET_;
6139 bssid->Reserved[0] = 2;
6140 } else if (subtype == WIFI_PROBERSP) {
6141 ie_offset = _PROBERSP_IE_OFFSET_;
6142 bssid->Reserved[0] = 3;
6143 } else {
6144 bssid->Reserved[0] = 0;
6145 ie_offset = _FIXED_IE_LENGTH_;
6146 }
6147 }
6148
6149 bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
6150
6151 /* below is to copy the information element */
6152 bssid->IELength = len;
6153 memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
6154
6155 /* get the signal strength */
6156 bssid->Rssi = precv_frame->attrib.phy_info.recvpower; /* in dBM.raw data */
6157 bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
6158 bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
6159 bssid->PhyInfo.Optimum_antenna = rtw_current_antenna(padapter);
6160
6161 /* checking SSID */
6162 p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
6163 if (!p)
6164 return _FAIL;
6165
6166 if (*(p + 1)) {
6167 if (len > NDIS_802_11_LENGTH_SSID)
6168 return _FAIL;
6169 memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
6170 bssid->Ssid.SsidLength = *(p + 1);
6171 } else {
6172 bssid->Ssid.SsidLength = 0;
6173 }
6174
6175 memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
6176
6177 /* checking rate info... */
6178 i = 0;
6179 p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
6180 if (p) {
6181 if (len > NDIS_802_11_LENGTH_RATES_EX)
6182 return _FAIL;
6183 memcpy(bssid->SupportedRates, (p + 2), len);
6184 i = len;
6185 }
6186
6187 p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
6188 if (p) {
6189 if (len > (NDIS_802_11_LENGTH_RATES_EX - i))
6190 return _FAIL;
6191 memcpy(bssid->SupportedRates + i, (p + 2), len);
6192 }
6193
6194 /* todo: */
6195 bssid->NetworkTypeInUse = Ndis802_11OFDM24;
6196
6197 if (bssid->IELength < 12)
6198 return _FAIL;
6199
6200 /* Checking for DSConfig */
6201 p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
6202
6203 bssid->Configuration.DSConfig = 0;
6204 bssid->Configuration.Length = 0;
6205
6206 if (p) {
6207 bssid->Configuration.DSConfig = *(p + 2);
6208 } else {/* In 5G, some ap do not have DSSET IE */
6209 /* checking HT info for channel */
6210 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
6211 if (p) {
6212 struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
6213 bssid->Configuration.DSConfig = HT_info->primary_channel;
6214 } else { /* use current channel */
6215 bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
6216 }
6217 }
6218
6219 memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
6220 bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
6221
6222 val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
6223
6224 if (val16 & BIT(0)) {
6225 bssid->InfrastructureMode = Ndis802_11Infrastructure;
6226 memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
6227 } else {
6228 bssid->InfrastructureMode = Ndis802_11IBSS;
6229 memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
6230 }
6231
6232 if (val16 & BIT(4))
6233 bssid->Privacy = 1;
6234 else
6235 bssid->Privacy = 0;
6236
6237 bssid->Configuration.ATIMWindow = 0;
6238
6239 /* 20/40 BSS Coexistence check */
6240 if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
6241 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6242 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
6243 if (p && len > 0) {
6244 struct HT_caps_element *pHT_caps;
6245 pHT_caps = (struct HT_caps_element *)(p + 2);
6246
6247 if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
6248 pmlmepriv->num_FortyMHzIntolerant++;
6249 } else {
6250 pmlmepriv->num_sta_no_ht++;
6251 }
6252 }
6253
6254 /* mark bss info receiving from nearby channel as SignalQuality 101 */
6255 if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
6256 bssid->PhyInfo.SignalQuality = 101;
6257 return _SUCCESS;
6258 }
6259
rtw_set_bssid(struct adapter * adapter,u8 * bssid)6260 static void rtw_set_bssid(struct adapter *adapter, u8 *bssid)
6261 {
6262 int i;
6263
6264 for (i = 0; i < ETH_ALEN; i++)
6265 rtw_write8(adapter, REG_BSSID + i, bssid[i]);
6266 }
6267
mlme_join(struct adapter * adapter,int type)6268 static void mlme_join(struct adapter *adapter, int type)
6269 {
6270 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
6271 u8 retry_limit = 0x30, reg;
6272 u32 reg32;
6273 int res;
6274
6275 switch (type) {
6276 case 0:
6277 /* prepare to join */
6278 /* enable to rx data frame, accept all data frame */
6279 rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
6280
6281 res = rtw_read32(adapter, REG_RCR, ®32);
6282 if (res)
6283 return;
6284
6285 rtw_write32(adapter, REG_RCR,
6286 reg32 | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
6287
6288 if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
6289 retry_limit = 48;
6290 } else {
6291 /* ad-hoc mode */
6292 retry_limit = 0x7;
6293 }
6294 break;
6295 case 1:
6296 /* joinbss_event call back when join res < 0 */
6297 rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
6298 break;
6299 case 2:
6300 /* sta add event call back */
6301 /* enable update TSF */
6302 res = rtw_read8(adapter, REG_BCN_CTRL, ®);
6303 if (res)
6304 return;
6305
6306 rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4)));
6307
6308 if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))
6309 retry_limit = 0x7;
6310 break;
6311 default:
6312 break;
6313 }
6314
6315 rtw_write16(adapter, REG_RL,
6316 retry_limit << RETRY_LIMIT_SHORT_SHIFT | retry_limit << RETRY_LIMIT_LONG_SHIFT);
6317 }
6318
start_create_ibss(struct adapter * padapter)6319 void start_create_ibss(struct adapter *padapter)
6320 {
6321 unsigned short caps;
6322 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6323 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6324 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
6325 pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6326 pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6327
6328 /* update wireless mode */
6329 update_wireless_mode(padapter);
6330
6331 /* udpate capability */
6332 caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
6333 update_capinfo(padapter, caps);
6334 if (caps & cap_IBSS) {/* adhoc master */
6335 rtw_write8(padapter, REG_SECCFG, 0xcf);
6336
6337 /* switch channel */
6338 /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
6339 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6340
6341 beacon_timing_control(padapter);
6342
6343 /* set msr to WIFI_FW_ADHOC_STATE */
6344 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
6345 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
6346
6347 /* issue beacon */
6348 if (send_beacon(padapter) == _FAIL) {
6349 report_join_res(padapter, -1);
6350 pmlmeinfo->state = WIFI_FW_NULL_STATE;
6351 } else {
6352 rtw_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
6353 mlme_join(padapter, 0);
6354
6355 report_join_res(padapter, 1);
6356 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
6357 rtw_indicate_connect(padapter);
6358 }
6359 } else {
6360 return;
6361 }
6362 /* update bc/mc sta_info */
6363 update_bmc_sta(padapter);
6364 }
6365
start_clnt_join(struct adapter * padapter)6366 void start_clnt_join(struct adapter *padapter)
6367 {
6368 unsigned short caps;
6369 u8 val8;
6370 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6371 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6372 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
6373 int beacon_timeout;
6374
6375 pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6376 pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6377
6378 /* update wireless mode */
6379 update_wireless_mode(padapter);
6380
6381 /* udpate capability */
6382 caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
6383 update_capinfo(padapter, caps);
6384 if (caps & cap_ESS) {
6385 Set_MSR(padapter, WIFI_FW_STATION_STATE);
6386
6387 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
6388
6389 rtw_write8(padapter, REG_SECCFG, val8);
6390
6391 /* switch channel */
6392 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6393
6394 /* here wait for receiving the beacon to start auth */
6395 /* and enable a timer */
6396 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
6397 set_link_timer(pmlmeext, beacon_timeout);
6398 _set_timer(&padapter->mlmepriv.assoc_timer,
6399 (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout);
6400
6401 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
6402 } else if (caps & cap_IBSS) { /* adhoc client */
6403 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
6404
6405 rtw_write8(padapter, REG_SECCFG, 0xcf);
6406
6407 /* switch channel */
6408 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6409
6410 beacon_timing_control(padapter);
6411
6412 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
6413
6414 report_join_res(padapter, 1);
6415 } else {
6416 return;
6417 }
6418 }
6419
start_clnt_auth(struct adapter * padapter)6420 void start_clnt_auth(struct adapter *padapter)
6421 {
6422 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6423 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6424
6425 _cancel_timer_ex(&pmlmeext->link_timer);
6426
6427 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
6428 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
6429
6430 pmlmeinfo->auth_seq = 1;
6431 pmlmeinfo->reauth_count = 0;
6432 pmlmeinfo->reassoc_count = 0;
6433 pmlmeinfo->link_count = 0;
6434 pmlmeext->retry = 0;
6435
6436 /* Because of AP's not receiving deauth before */
6437 /* AP may: 1)not response auth or 2)deauth us after link is complete */
6438 /* issue deauth before issuing auth to deal with the situation */
6439 /* Commented by Albert 2012/07/21 */
6440 /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
6441 issue_deauth(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
6442
6443 issue_auth(padapter, NULL, 0);
6444
6445 set_link_timer(pmlmeext, REAUTH_TO);
6446 }
6447
start_clnt_assoc(struct adapter * padapter)6448 void start_clnt_assoc(struct adapter *padapter)
6449 {
6450 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6451 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6452
6453 _cancel_timer_ex(&pmlmeext->link_timer);
6454
6455 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
6456 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
6457
6458 issue_assocreq(padapter);
6459
6460 set_link_timer(pmlmeext, REASSOC_TO);
6461 }
6462
receive_disconnect(struct adapter * padapter,unsigned char * MacAddr,unsigned short reason)6463 void receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
6464 {
6465 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6466 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6467
6468 /* check A3 */
6469 if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
6470 return;
6471
6472 if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
6473 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
6474 pmlmeinfo->state = WIFI_FW_NULL_STATE;
6475 report_del_sta_event(padapter, MacAddr, reason);
6476 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
6477 pmlmeinfo->state = WIFI_FW_NULL_STATE;
6478 report_join_res(padapter, -2);
6479 }
6480 }
6481 }
6482
process_80211d(struct adapter * padapter,struct wlan_bssid_ex * bssid)6483 static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
6484 {
6485 struct registry_priv *pregistrypriv;
6486 struct mlme_ext_priv *pmlmeext;
6487 struct rt_channel_info *chplan_new;
6488 u8 channel;
6489 u8 i;
6490
6491 pregistrypriv = &padapter->registrypriv;
6492 pmlmeext = &padapter->mlmeextpriv;
6493
6494 /* Adjust channel plan by AP Country IE */
6495 if (pregistrypriv->enable80211d &&
6496 (!pmlmeext->update_channel_plan_by_ap_done)) {
6497 u8 *ie, *p;
6498 u32 len;
6499 struct rt_channel_plan chplan_ap;
6500 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
6501 u8 country[4];
6502 u8 fcn; /* first channel number */
6503 u8 noc; /* number of channel */
6504 u8 j, k;
6505
6506 ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
6507 if (!ie)
6508 return;
6509 if (len < 6)
6510 return;
6511 ie += 2;
6512 p = ie;
6513 ie += len;
6514
6515 memset(country, 0, 4);
6516 memcpy(country, p, 3);
6517 p += 3;
6518
6519 i = 0;
6520 while ((ie - p) >= 3) {
6521 fcn = *(p++);
6522 noc = *(p++);
6523 p++;
6524
6525 for (j = 0; j < noc; j++) {
6526 channel = fcn + j;
6527 chplan_ap.Channel[i++] = channel;
6528 }
6529 }
6530 chplan_ap.Len = i;
6531
6532 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
6533
6534 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
6535 chplan_new = pmlmeext->channel_set;
6536
6537 i = 0;
6538 j = 0;
6539 k = 0;
6540 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
6541 do {
6542 if ((i == MAX_CHANNEL_NUM) ||
6543 (chplan_sta[i].ChannelNum == 0))
6544 break;
6545
6546 if (j == chplan_ap.Len)
6547 break;
6548
6549 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
6550 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6551 chplan_new[k].ScanType = SCAN_ACTIVE;
6552 i++;
6553 j++;
6554 k++;
6555 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
6556 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6557 chplan_new[k].ScanType = SCAN_PASSIVE;
6558 i++;
6559 k++;
6560 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
6561 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6562 chplan_new[k].ScanType = SCAN_ACTIVE;
6563 j++;
6564 k++;
6565 }
6566 } while (1);
6567
6568 /* change AP not support channel to Passive scan */
6569 while ((i < MAX_CHANNEL_NUM) &&
6570 (chplan_sta[i].ChannelNum != 0) &&
6571 (chplan_sta[i].ChannelNum <= 14)) {
6572 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6573 chplan_new[k].ScanType = SCAN_PASSIVE;
6574 i++;
6575 k++;
6576 }
6577
6578 /* add channel AP supported */
6579 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
6580 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6581 chplan_new[k].ScanType = SCAN_ACTIVE;
6582 j++;
6583 k++;
6584 }
6585 } else {
6586 /* keep original STA 2.4G channel plan */
6587 while ((i < MAX_CHANNEL_NUM) &&
6588 (chplan_sta[i].ChannelNum != 0) &&
6589 (chplan_sta[i].ChannelNum <= 14)) {
6590 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6591 chplan_new[k].ScanType = chplan_sta[i].ScanType;
6592 i++;
6593 k++;
6594 }
6595
6596 /* skip AP 2.4G channel plan */
6597 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
6598 j++;
6599 }
6600
6601 /* keep original STA 5G channel plan */
6602 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
6603 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6604 chplan_new[k].ScanType = chplan_sta[i].ScanType;
6605 i++;
6606 k++;
6607 }
6608
6609 pmlmeext->update_channel_plan_by_ap_done = 1;
6610 }
6611
6612 /* If channel is used by AP, set channel scan type to active */
6613 channel = bssid->Configuration.DSConfig;
6614 chplan_new = pmlmeext->channel_set;
6615 i = 0;
6616 while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
6617 if (chplan_new[i].ChannelNum == channel) {
6618 if (chplan_new[i].ScanType == SCAN_PASSIVE)
6619 chplan_new[i].ScanType = SCAN_ACTIVE;
6620 break;
6621 }
6622 i++;
6623 }
6624 }
6625
6626 /****************************************************************************
6627
6628 Following are the functions to report events
6629
6630 *****************************************************************************/
6631
report_survey_event(struct adapter * padapter,struct recv_frame * precv_frame)6632 void report_survey_event(struct adapter *padapter, struct recv_frame *precv_frame)
6633 {
6634 struct cmd_obj *pcmd_obj;
6635 u8 *pevtcmd;
6636 u32 cmdsz;
6637 struct survey_event *psurvey_evt;
6638 struct C2HEvent_Header *pc2h_evt_hdr;
6639 struct mlme_ext_priv *pmlmeext;
6640 struct cmd_priv *pcmdpriv;
6641 /* u8 *pframe = precv_frame->rx_data; */
6642 /* uint len = precv_frame->len; */
6643
6644 if (!padapter)
6645 return;
6646
6647 pmlmeext = &padapter->mlmeextpriv;
6648 pcmdpriv = &padapter->cmdpriv;
6649
6650 pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC);
6651 if (!pcmd_obj)
6652 return;
6653
6654 cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
6655 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
6656 if (!pevtcmd) {
6657 kfree(pcmd_obj);
6658 return;
6659 }
6660
6661 INIT_LIST_HEAD(&pcmd_obj->list);
6662
6663 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6664 pcmd_obj->cmdsz = cmdsz;
6665 pcmd_obj->parmbuf = pevtcmd;
6666
6667 pcmd_obj->rsp = NULL;
6668 pcmd_obj->rspsz = 0;
6669
6670 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6671 pc2h_evt_hdr->len = sizeof(struct survey_event);
6672 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
6673 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6674
6675 psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6676
6677 if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
6678 kfree(pcmd_obj);
6679 kfree(pevtcmd);
6680 return;
6681 }
6682
6683 process_80211d(padapter, &psurvey_evt->bss);
6684
6685 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6686
6687 pmlmeext->sitesurvey_res.bss_cnt++;
6688 }
6689
report_surveydone_event(struct adapter * padapter)6690 void report_surveydone_event(struct adapter *padapter)
6691 {
6692 struct cmd_obj *pcmd_obj;
6693 u8 *pevtcmd;
6694 u32 cmdsz;
6695 struct surveydone_event *psurveydone_evt;
6696 struct C2HEvent_Header *pc2h_evt_hdr;
6697 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6698 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6699
6700 pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_KERNEL);
6701 if (!pcmd_obj)
6702 return;
6703
6704 cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
6705 pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
6706 if (!pevtcmd) {
6707 kfree(pcmd_obj);
6708 return;
6709 }
6710
6711 INIT_LIST_HEAD(&pcmd_obj->list);
6712
6713 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6714 pcmd_obj->cmdsz = cmdsz;
6715 pcmd_obj->parmbuf = pevtcmd;
6716
6717 pcmd_obj->rsp = NULL;
6718 pcmd_obj->rspsz = 0;
6719
6720 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6721 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
6722 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
6723 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6724
6725 psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6726 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
6727
6728 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6729 }
6730
report_join_res(struct adapter * padapter,int res)6731 void report_join_res(struct adapter *padapter, int res)
6732 {
6733 struct cmd_obj *pcmd_obj;
6734 u8 *pevtcmd;
6735 u32 cmdsz;
6736 struct joinbss_event *pjoinbss_evt;
6737 struct C2HEvent_Header *pc2h_evt_hdr;
6738 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6739 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6740 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6741
6742 pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC);
6743 if (!pcmd_obj)
6744 return;
6745
6746 cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
6747 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
6748 if (!pevtcmd) {
6749 kfree(pcmd_obj);
6750 return;
6751 }
6752
6753 INIT_LIST_HEAD(&pcmd_obj->list);
6754
6755 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6756 pcmd_obj->cmdsz = cmdsz;
6757 pcmd_obj->parmbuf = pevtcmd;
6758
6759 pcmd_obj->rsp = NULL;
6760 pcmd_obj->rspsz = 0;
6761
6762 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6763 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
6764 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
6765 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6766
6767 pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6768 memcpy((unsigned char *)(&pjoinbss_evt->network.network), &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
6769 pjoinbss_evt->network.join_res = res;
6770 pjoinbss_evt->network.aid = res;
6771
6772 rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
6773
6774 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6775 }
6776
report_del_sta_event(struct adapter * padapter,unsigned char * MacAddr,unsigned short reason)6777 void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
6778 {
6779 struct cmd_obj *pcmd_obj;
6780 u8 *pevtcmd;
6781 u32 cmdsz;
6782 struct sta_info *psta;
6783 int mac_id;
6784 struct stadel_event *pdel_sta_evt;
6785 struct C2HEvent_Header *pc2h_evt_hdr;
6786 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6787 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6788
6789 pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC);
6790 if (!pcmd_obj)
6791 return;
6792
6793 cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
6794 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
6795 if (!pevtcmd) {
6796 kfree(pcmd_obj);
6797 return;
6798 }
6799
6800 INIT_LIST_HEAD(&pcmd_obj->list);
6801
6802 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6803 pcmd_obj->cmdsz = cmdsz;
6804 pcmd_obj->parmbuf = pevtcmd;
6805
6806 pcmd_obj->rsp = NULL;
6807 pcmd_obj->rspsz = 0;
6808
6809 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6810 pc2h_evt_hdr->len = sizeof(struct stadel_event);
6811 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
6812 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6813
6814 pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6815 memcpy((unsigned char *)(&pdel_sta_evt->macaddr), MacAddr, ETH_ALEN);
6816 memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
6817
6818 psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
6819 if (psta)
6820 mac_id = (int)psta->mac_id;
6821 else
6822 mac_id = (-1);
6823
6824 pdel_sta_evt->mac_id = mac_id;
6825
6826 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6827 }
6828
report_add_sta_event(struct adapter * padapter,unsigned char * MacAddr,int cam_idx)6829 void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
6830 {
6831 struct cmd_obj *pcmd_obj;
6832 u8 *pevtcmd;
6833 u32 cmdsz;
6834 struct stassoc_event *padd_sta_evt;
6835 struct C2HEvent_Header *pc2h_evt_hdr;
6836 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6837 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6838
6839 pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_KERNEL);
6840 if (!pcmd_obj)
6841 return;
6842
6843 cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
6844 pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
6845 if (!pevtcmd) {
6846 kfree(pcmd_obj);
6847 return;
6848 }
6849
6850 INIT_LIST_HEAD(&pcmd_obj->list);
6851
6852 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
6853 pcmd_obj->cmdsz = cmdsz;
6854 pcmd_obj->parmbuf = pevtcmd;
6855
6856 pcmd_obj->rsp = NULL;
6857 pcmd_obj->rspsz = 0;
6858
6859 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
6860 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
6861 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
6862 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
6863
6864 padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
6865 memcpy((unsigned char *)(&padd_sta_evt->macaddr), MacAddr, ETH_ALEN);
6866 padd_sta_evt->cam_id = cam_idx;
6867
6868 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
6869 }
6870
6871 /****************************************************************************
6872
6873 Following are the event callback functions
6874
6875 *****************************************************************************/
6876
6877 /* for sta/adhoc mode */
update_sta_info(struct adapter * padapter,struct sta_info * psta)6878 void update_sta_info(struct adapter *padapter, struct sta_info *psta)
6879 {
6880 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6881 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6882 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6883
6884 /* ERP */
6885 VCS_update(padapter, psta);
6886
6887 /* HT */
6888 if (pmlmepriv->htpriv.ht_option) {
6889 psta->htpriv.ht_option = true;
6890
6891 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
6892
6893 if (support_short_GI(padapter, &pmlmeinfo->HT_caps))
6894 psta->htpriv.sgi = true;
6895
6896 psta->qos_option = true;
6897 } else {
6898 psta->htpriv.ht_option = false;
6899
6900 psta->htpriv.ampdu_enable = false;
6901
6902 psta->htpriv.sgi = false;
6903 psta->qos_option = false;
6904 }
6905 psta->htpriv.bwmode = pmlmeext->cur_bwmode;
6906 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
6907
6908 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
6909 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
6910
6911 /* QoS */
6912 if (pmlmepriv->qospriv.qos_option)
6913 psta->qos_option = true;
6914
6915 psta->state = _FW_LINKED;
6916 }
6917
rtw_reset_dm_func_flag(struct adapter * adapter)6918 static void rtw_reset_dm_func_flag(struct adapter *adapter)
6919 {
6920 struct hal_data_8188e *haldata = &adapter->haldata;
6921 struct dm_priv *dmpriv = &haldata->dmpriv;
6922 struct odm_dm_struct *odmpriv = &haldata->odmpriv;
6923
6924 odmpriv->SupportAbility = dmpriv->InitODMFlag;
6925 }
6926
rtw_clear_dm_func_flag(struct adapter * adapter)6927 static void rtw_clear_dm_func_flag(struct adapter *adapter)
6928 {
6929 struct hal_data_8188e *haldata = &adapter->haldata;
6930 struct odm_dm_struct *odmpriv = &haldata->odmpriv;
6931
6932 odmpriv->SupportAbility = 0;
6933 }
6934
mlmeext_joinbss_event_callback(struct adapter * padapter,int join_res)6935 void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
6936 {
6937 struct sta_info *psta, *psta_bmc;
6938 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6939 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6940 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
6941 struct sta_priv *pstapriv = &padapter->stapriv;
6942 u16 media_status;
6943
6944 if (join_res < 0) {
6945 mlme_join(padapter, 1);
6946 rtw_set_bssid(padapter, null_addr);
6947
6948 /* restore to initial setting. */
6949 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
6950
6951 return;
6952 }
6953
6954 if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
6955 /* for bc/mc */
6956 psta_bmc = rtw_get_bcmc_stainfo(padapter);
6957 if (psta_bmc) {
6958 pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
6959 update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
6960 Update_RA_Entry(padapter, psta_bmc->mac_id);
6961 }
6962 }
6963
6964 /* turn on dynamic functions */
6965 rtw_reset_dm_func_flag(padapter);
6966
6967 /* update IOT-releated issue */
6968 update_IOT_info(padapter);
6969
6970 rtw_set_basic_rate(padapter, cur_network->SupportedRates);
6971
6972 /* BCN interval */
6973 rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
6974
6975 /* udpate capability */
6976 update_capinfo(padapter, pmlmeinfo->capability);
6977
6978 /* WMM, Update EDCA param */
6979 WMMOnAssocRsp(padapter);
6980
6981 /* HT */
6982 HTOnAssocRsp(padapter);
6983
6984 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6985
6986 psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
6987 if (psta) { /* only for infra. mode */
6988 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
6989
6990 psta->wireless_mode = pmlmeext->cur_wireless_mode;
6991
6992 /* set per sta rate after updating HT cap. */
6993 set_sta_rate(padapter, psta);
6994 rtw_set_max_rpt_macid(padapter, psta->mac_id);
6995
6996 media_status = (psta->mac_id << 8) | 1; /* MACID|OPMODE: 1 means connect */
6997 rtl8188e_set_FwMediaStatus_cmd(padapter, media_status);
6998 }
6999
7000 mlme_join(padapter, 2);
7001
7002 if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
7003 /* correcting TSF */
7004 correct_TSF(padapter);
7005 }
7006 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
7007 }
7008
mlmeext_sta_add_event_callback(struct adapter * padapter,struct sta_info * psta)7009 void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
7010 {
7011 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7012 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7013
7014 if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
7015 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
7016 /* nothing to do */
7017 } else { /* adhoc client */
7018 /* correcting TSF */
7019 correct_TSF(padapter);
7020
7021 /* start beacon */
7022 if (send_beacon(padapter) == _FAIL) {
7023 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
7024 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
7025 return;
7026 }
7027 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
7028 }
7029 mlme_join(padapter, 2);
7030 }
7031
7032 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
7033
7034 /* rate radaptive */
7035 Update_RA_Entry(padapter, psta->mac_id);
7036
7037 /* update adhoc sta_info */
7038 update_sta_info(padapter, psta);
7039 }
7040
mlme_disconnect(struct adapter * adapter)7041 static void mlme_disconnect(struct adapter *adapter)
7042 {
7043 int res;
7044 u8 reg;
7045
7046 /* Set RCR to not to receive data frame when NO LINK state */
7047 /* reject all data frames */
7048 rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
7049
7050 /* reset TSF */
7051 rtw_write8(adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
7052
7053 /* disable update TSF */
7054
7055 res = rtw_read8(adapter, REG_BCN_CTRL, ®);
7056 if (res)
7057 return;
7058
7059 rtw_write8(adapter, REG_BCN_CTRL, reg | BIT(4));
7060 }
7061
mlmeext_sta_del_event_callback(struct adapter * padapter)7062 void mlmeext_sta_del_event_callback(struct adapter *padapter)
7063 {
7064 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7065 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7066
7067 if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
7068 mlme_disconnect(padapter);
7069 rtw_set_bssid(padapter, null_addr);
7070
7071 /* restore to initial setting. */
7072 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7073
7074 /* switch to the 20M Hz mode after disconnect */
7075 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7076 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7077
7078 /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
7079 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7080
7081 flush_all_cam_entry(padapter);
7082
7083 pmlmeinfo->state = WIFI_FW_NULL_STATE;
7084
7085 /* set MSR to no link state -> infra. mode */
7086 Set_MSR(padapter, _HW_STATE_STATION_);
7087
7088 _cancel_timer_ex(&pmlmeext->link_timer);
7089 }
7090 }
7091
7092 /****************************************************************************
7093
7094 Following are the functions for the timer handlers
7095
7096 *****************************************************************************/
chk_ap_is_alive(struct sta_info * psta)7097 static u8 chk_ap_is_alive(struct sta_info *psta)
7098 {
7099 u8 ret = false;
7100
7101 if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
7102 sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
7103 sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
7104 ret = false;
7105 else
7106 ret = true;
7107
7108 sta_update_last_rx_pkts(psta);
7109
7110 return ret;
7111 }
7112
rtl8188e_sreset_linked_status_check(struct adapter * padapter)7113 static int rtl8188e_sreset_linked_status_check(struct adapter *padapter)
7114 {
7115 u32 rx_dma_status;
7116 int res;
7117 u8 reg;
7118
7119 res = rtw_read32(padapter, REG_RXDMA_STATUS, &rx_dma_status);
7120 if (res)
7121 return res;
7122
7123 if (rx_dma_status != 0x00)
7124 rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
7125
7126 return rtw_read8(padapter, REG_FMETHR, ®);
7127 }
7128
linked_status_chk(struct adapter * padapter)7129 void linked_status_chk(struct adapter *padapter)
7130 {
7131 u32 i;
7132 struct sta_info *psta;
7133 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7134 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7135 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7136 struct sta_priv *pstapriv = &padapter->stapriv;
7137
7138 rtl8188e_sreset_linked_status_check(padapter);
7139
7140 if (is_client_associated_to_ap(padapter)) {
7141 /* linked infrastructure client mode */
7142
7143 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
7144 int rx_chk_limit;
7145
7146 rx_chk_limit = 4;
7147 psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
7148 if (psta) {
7149 bool is_p2p_enable = false;
7150 is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
7151
7152 if (!chk_ap_is_alive(psta))
7153 rx_chk = _FAIL;
7154
7155 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
7156 tx_chk = _FAIL;
7157
7158 if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
7159 u8 backup_oper_channel = 0;
7160
7161 /* switch to correct channel of current network before issue keep-alive frames */
7162 if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
7163 backup_oper_channel = rtw_get_oper_ch(padapter);
7164 SelectChannel(padapter, pmlmeext->cur_channel);
7165 }
7166
7167 if (rx_chk != _SUCCESS)
7168 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
7169
7170 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
7171 tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
7172 /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
7173 if (tx_chk == _SUCCESS && !is_p2p_enable)
7174 rx_chk = _SUCCESS;
7175 }
7176
7177 /* back to the original operation channel */
7178 if (backup_oper_channel > 0)
7179 SelectChannel(padapter, backup_oper_channel);
7180 } else {
7181 if (rx_chk != _SUCCESS) {
7182 if (pmlmeext->retry == 0) {
7183 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7184 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7185 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7186 }
7187 }
7188
7189 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) {
7190 tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
7191 }
7192 }
7193
7194 if (rx_chk == _FAIL) {
7195 pmlmeext->retry++;
7196 if (pmlmeext->retry > rx_chk_limit) {
7197 receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
7198 WLAN_REASON_EXPIRATION_CHK);
7199 return;
7200 }
7201 } else {
7202 pmlmeext->retry = 0;
7203 }
7204
7205 if (tx_chk == _FAIL) {
7206 pmlmeinfo->link_count &= 0xf;
7207 } else {
7208 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
7209 pmlmeinfo->link_count = 0;
7210 }
7211 } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
7212 } else if (is_client_associated_to_ibss(padapter)) {
7213 /* linked IBSS mode */
7214 /* for each assoc list entry to check the rx pkt counter */
7215 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
7216 if (pmlmeinfo->FW_sta_info[i].status == 1) {
7217 psta = pmlmeinfo->FW_sta_info[i].psta;
7218
7219 if (psta == NULL)
7220 continue;
7221 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
7222 if (pmlmeinfo->FW_sta_info[i].retry < 3) {
7223 pmlmeinfo->FW_sta_info[i].retry++;
7224 } else {
7225 pmlmeinfo->FW_sta_info[i].retry = 0;
7226 pmlmeinfo->FW_sta_info[i].status = 0;
7227 report_del_sta_event(padapter, psta->hwaddr
7228 , 65535/* indicate disconnect caused by no rx */
7229 );
7230 }
7231 } else {
7232 pmlmeinfo->FW_sta_info[i].retry = 0;
7233 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
7234 }
7235 }
7236 }
7237 }
7238 }
7239
survey_timer_hdl(struct adapter * padapter)7240 void survey_timer_hdl(struct adapter *padapter)
7241 {
7242 struct cmd_obj *ph2c;
7243 struct sitesurvey_parm *psurveyPara;
7244 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7245 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7246 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
7247
7248 /* issue rtw_sitesurvey_cmd */
7249 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
7250 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
7251 pmlmeext->sitesurvey_res.channel_idx++;
7252
7253 if (pmlmeext->scan_abort) {
7254 if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) {
7255 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
7256 pmlmeext->sitesurvey_res.channel_idx = 3;
7257 } else {
7258 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
7259 }
7260
7261 pmlmeext->scan_abort = false;/* reset */
7262 }
7263
7264 ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
7265 if (!ph2c)
7266 goto exit_survey_timer_hdl;
7267
7268 psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC);
7269 if (!psurveyPara) {
7270 kfree(ph2c);
7271 goto exit_survey_timer_hdl;
7272 }
7273
7274 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
7275 rtw_enqueue_cmd(pcmdpriv, ph2c);
7276 }
7277
7278 exit_survey_timer_hdl:
7279 return;
7280 }
7281
link_timer_hdl(struct adapter * padapter)7282 void link_timer_hdl(struct adapter *padapter)
7283 {
7284 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7285 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7286
7287 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
7288 pmlmeinfo->state = WIFI_FW_NULL_STATE;
7289 report_join_res(padapter, -3);
7290 } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
7291 /* re-auth timer */
7292 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
7293 pmlmeinfo->state = 0;
7294 report_join_res(padapter, -1);
7295 return;
7296 }
7297
7298 pmlmeinfo->auth_seq = 1;
7299 issue_auth(padapter, NULL, 0);
7300 set_link_timer(pmlmeext, REAUTH_TO);
7301 } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
7302 /* re-assoc timer */
7303 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
7304 pmlmeinfo->state = WIFI_FW_NULL_STATE;
7305 report_join_res(padapter, -2);
7306 return;
7307 }
7308
7309 issue_assocreq(padapter);
7310 set_link_timer(pmlmeext, REASSOC_TO);
7311 }
7312 }
7313
addba_timer_hdl(struct sta_info * psta)7314 void addba_timer_hdl(struct sta_info *psta)
7315 {
7316 struct ht_priv *phtpriv;
7317
7318 if (!psta)
7319 return;
7320
7321 phtpriv = &psta->htpriv;
7322
7323 if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
7324 if (phtpriv->candidate_tid_bitmap)
7325 phtpriv->candidate_tid_bitmap = 0x0;
7326 }
7327 }
7328
NULL_hdl(struct adapter * padapter,u8 * pbuf)7329 u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
7330 {
7331 return H2C_SUCCESS;
7332 }
7333
setopmode_hdl(struct adapter * padapter,u8 * pbuf)7334 u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
7335 {
7336 u8 type;
7337 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7338 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7339 struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
7340
7341 if (psetop->mode == Ndis802_11APMode) {
7342 pmlmeinfo->state = WIFI_FW_AP_STATE;
7343 type = _HW_STATE_AP_;
7344 } else if (psetop->mode == Ndis802_11Infrastructure) {
7345 pmlmeinfo->state &= ~(BIT(0) | BIT(1));/* clear state */
7346 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
7347 type = _HW_STATE_STATION_;
7348 } else if (psetop->mode == Ndis802_11IBSS) {
7349 type = _HW_STATE_ADHOC_;
7350 } else {
7351 type = _HW_STATE_NOLINK_;
7352 }
7353
7354 rtw_set_opmode(padapter, type);
7355
7356 return H2C_SUCCESS;
7357 }
7358
createbss_hdl(struct adapter * padapter,u8 * pbuf)7359 u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
7360 {
7361 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7362 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7363 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
7364 struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
7365 /* u32 initialgain; */
7366
7367 if (pparm->network.InfrastructureMode == Ndis802_11APMode) {
7368 if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
7369 /* todo: */
7370 return H2C_SUCCESS;
7371 }
7372 }
7373
7374 /* below is for ad-hoc master */
7375 if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
7376 rtw_joinbss_reset(padapter);
7377
7378 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7379 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7380 pmlmeinfo->ERP_enable = 0;
7381 pmlmeinfo->WMM_enable = 0;
7382 pmlmeinfo->HT_enable = 0;
7383 pmlmeinfo->HT_caps_enable = 0;
7384 pmlmeinfo->HT_info_enable = 0;
7385 pmlmeinfo->agg_enable_bitmap = 0;
7386 pmlmeinfo->candidate_tid_bitmap = 0;
7387
7388 /* disable dynamic functions, such as high power, DIG */
7389 Save_DM_Func_Flag(padapter);
7390 rtw_clear_dm_func_flag(padapter);
7391
7392 /* cancel link timer */
7393 _cancel_timer_ex(&pmlmeext->link_timer);
7394
7395 /* clear CAM */
7396 flush_all_cam_entry(padapter);
7397
7398 memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, IELength));
7399 pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
7400
7401 if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
7402 return H2C_PARAMETERS_ERROR;
7403
7404 memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
7405
7406 start_create_ibss(padapter);
7407 }
7408
7409 return H2C_SUCCESS;
7410 }
7411
join_cmd_hdl(struct adapter * padapter,u8 * pbuf)7412 u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
7413 {
7414 struct ndis_802_11_var_ie *pIE;
7415 struct registry_priv *pregpriv = &padapter->registrypriv;
7416 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7417 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7418 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
7419 struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
7420 u32 i;
7421
7422 /* check already connecting to AP or not */
7423 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
7424 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
7425 issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
7426
7427 pmlmeinfo->state = WIFI_FW_NULL_STATE;
7428
7429 /* clear CAM */
7430 flush_all_cam_entry(padapter);
7431
7432 _cancel_timer_ex(&pmlmeext->link_timer);
7433
7434 /* set MSR to nolink -> infra. mode */
7435 Set_MSR(padapter, _HW_STATE_STATION_);
7436
7437 mlme_disconnect(padapter);
7438 }
7439
7440 rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, false);
7441
7442 rtw_joinbss_reset(padapter);
7443
7444 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7445 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7446 pmlmeinfo->ERP_enable = 0;
7447 pmlmeinfo->WMM_enable = 0;
7448 pmlmeinfo->HT_enable = 0;
7449 pmlmeinfo->HT_caps_enable = 0;
7450 pmlmeinfo->HT_info_enable = 0;
7451 pmlmeinfo->agg_enable_bitmap = 0;
7452 pmlmeinfo->candidate_tid_bitmap = 0;
7453 pmlmeinfo->bwmode_updated = false;
7454
7455 memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, IELength));
7456 pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
7457
7458 if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
7459 return H2C_PARAMETERS_ERROR;
7460
7461 memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
7462
7463 /* Check AP vendor to move rtw_joinbss_cmd() */
7464
7465 for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->IELength;) {
7466 pIE = (struct ndis_802_11_var_ie *)(pnetwork->IEs + i);
7467
7468 switch (pIE->ElementID) {
7469 case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
7470 if (!memcmp(pIE->data, WMM_OUI, 4))
7471 pmlmeinfo->WMM_enable = 1;
7472 break;
7473 case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */
7474 pmlmeinfo->HT_caps_enable = 1;
7475 break;
7476 case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */
7477 pmlmeinfo->HT_info_enable = 1;
7478
7479 /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
7480 {
7481 struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
7482
7483 if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
7484 /* switch to the 40M Hz mode according to the AP */
7485 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
7486 switch (pht_info->infos[0] & 0x3) {
7487 case 1:
7488 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
7489 break;
7490 case 3:
7491 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
7492 break;
7493 default:
7494 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7495 break;
7496 }
7497 }
7498 }
7499 break;
7500 default:
7501 break;
7502 }
7503
7504 i += (pIE->Length + 2);
7505 }
7506 /* disable dynamic functions, such as high power, DIG */
7507
7508 /* config the initial gain under linking, need to write the BB registers */
7509
7510 rtw_set_bssid(padapter, pmlmeinfo->network.MacAddress);
7511 mlme_join(padapter, 0);
7512
7513 /* cancel link timer */
7514 _cancel_timer_ex(&pmlmeext->link_timer);
7515
7516 start_clnt_join(padapter);
7517
7518 return H2C_SUCCESS;
7519 }
7520
disconnect_hdl(struct adapter * padapter,unsigned char * pbuf)7521 u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
7522 {
7523 struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
7524 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7525 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7526 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
7527 u8 val8;
7528 int res;
7529
7530 if (is_client_associated_to_ap(padapter))
7531 issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100);
7532
7533 mlme_disconnect(padapter);
7534 rtw_set_bssid(padapter, null_addr);
7535
7536 /* restore to initial setting. */
7537 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7538
7539 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
7540 /* Stop BCN */
7541 res = rtw_read8(padapter, REG_BCN_CTRL, &val8);
7542 if (res)
7543 return H2C_DROPPED;
7544
7545 rtw_write8(padapter, REG_BCN_CTRL, val8 & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT)));
7546 }
7547
7548 /* set MSR to no link state -> infra. mode */
7549 Set_MSR(padapter, _HW_STATE_STATION_);
7550
7551 pmlmeinfo->state = WIFI_FW_NULL_STATE;
7552
7553 /* switch to the 20M Hz mode after disconnect */
7554 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7555 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7556
7557 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7558
7559 flush_all_cam_entry(padapter);
7560
7561 _cancel_timer_ex(&pmlmeext->link_timer);
7562
7563 rtw_free_uc_swdec_pending_queue(padapter);
7564
7565 return H2C_SUCCESS;
7566 }
7567
rtw_scan_ch_decision(struct adapter * padapter,struct rtw_ieee80211_channel * out,u32 out_num,struct rtw_ieee80211_channel * in,u32 in_num)7568 static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
7569 u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
7570 {
7571 int i, j;
7572 int set_idx;
7573 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7574
7575 /* clear out first */
7576 memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num);
7577
7578 /* acquire channels from in */
7579 j = 0;
7580 for (i = 0; i < in_num; i++) {
7581 set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
7582 if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
7583 set_idx >= 0) {
7584 memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
7585
7586 if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
7587 out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
7588
7589 j++;
7590 }
7591 if (j >= out_num)
7592 break;
7593 }
7594
7595 /* if out is empty, use channel_set as default */
7596 if (j == 0) {
7597 for (i = 0; i < pmlmeext->max_chan_nums; i++) {
7598 out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
7599
7600 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
7601 out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
7602
7603 j++;
7604 }
7605 }
7606
7607 return j;
7608 }
7609
sitesurvey_cmd_hdl(struct adapter * padapter,u8 * pbuf)7610 u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
7611 {
7612 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7613 struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
7614 u8 bdelayscan = false;
7615 u32 i;
7616 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
7617
7618 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
7619 /* for first time sitesurvey_cmd */
7620
7621 pmlmeext->sitesurvey_res.state = SCAN_START;
7622 pmlmeext->sitesurvey_res.bss_cnt = 0;
7623 pmlmeext->sitesurvey_res.channel_idx = 0;
7624
7625 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
7626 if (pparm->ssid[i].SsidLength) {
7627 memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
7628 pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
7629 } else {
7630 pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
7631 }
7632 }
7633
7634 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
7635 , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
7636 , pparm->ch, pparm->ch_num
7637 );
7638
7639 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
7640
7641 /* issue null data if associating to the AP */
7642 if (is_client_associated_to_ap(padapter)) {
7643 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
7644
7645 issue_nulldata(padapter, NULL, 1, 3, 500);
7646
7647 bdelayscan = true;
7648 }
7649 if (bdelayscan) {
7650 /* delay 50ms to protect nulldata(1). */
7651 set_survey_timer(pmlmeext, 50);
7652 return H2C_SUCCESS;
7653 }
7654 }
7655
7656 if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
7657 /* disable dynamic functions, such as high power, DIG */
7658 Save_DM_Func_Flag(padapter);
7659 rtw_clear_dm_func_flag(padapter);
7660
7661 /* config the initial gain under scanning, need to write the BB registers */
7662 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
7663 rtw_set_initial_gain(padapter, 0x1e);
7664 else
7665 rtw_set_initial_gain(padapter, 0x28);
7666
7667
7668 /* set MSR to no link state */
7669 Set_MSR(padapter, _HW_STATE_NOLINK_);
7670
7671 rtw_mlme_under_site_survey(padapter);
7672
7673 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
7674 }
7675
7676 site_survey(padapter);
7677
7678 return H2C_SUCCESS;
7679 }
7680
setauth_hdl(struct adapter * padapter,unsigned char * pbuf)7681 u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
7682 {
7683 struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
7684 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7685 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7686
7687 if (pparm->mode < 4)
7688 pmlmeinfo->auth_algo = pparm->mode;
7689 return H2C_SUCCESS;
7690 }
7691
setkey_hdl(struct adapter * padapter,u8 * pbuf)7692 u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
7693 {
7694 unsigned short ctrl;
7695 struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
7696 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7697 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7698 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
7699
7700 /* main tx key for wep. */
7701 if (pparm->set_tx)
7702 pmlmeinfo->key_index = pparm->keyid;
7703
7704 /* write cam */
7705 ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
7706
7707 write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
7708
7709 return H2C_SUCCESS;
7710 }
7711
set_stakey_hdl(struct adapter * padapter,u8 * pbuf)7712 u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
7713 {
7714 u16 ctrl = 0;
7715 u8 cam_id;/* cam_entry */
7716 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7717 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7718 struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
7719
7720 /* cam_entry: */
7721 /* 0~3 for default key */
7722
7723 /* for concurrent mode (ap+sta): */
7724 /* default key is disable, using sw encrypt/decrypt */
7725 /* cam_entry = 4 for sta mode (macid = 0) */
7726 /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
7727
7728 /* for concurrent mode (sta+sta): */
7729 /* default key is disable, using sw encrypt/decrypt */
7730 /* cam_entry = 4 mapping to macid = 0 */
7731 /* cam_entry = 5 mapping to macid = 2 */
7732
7733 cam_id = 4;
7734
7735 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
7736 struct sta_info *psta;
7737 struct sta_priv *pstapriv = &padapter->stapriv;
7738
7739 if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */ {
7740 clear_cam_entry(padapter, pparm->id);
7741 return H2C_SUCCESS_RSP;
7742 }
7743
7744 psta = rtw_get_stainfo(pstapriv, pparm->addr);
7745 if (psta) {
7746 ctrl = (BIT(15) | ((pparm->algorithm) << 2));
7747
7748 if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA - 4)))
7749 return H2C_REJECTED;
7750
7751 cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
7752
7753 write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
7754
7755 return H2C_SUCCESS_RSP;
7756 } else {
7757 return H2C_REJECTED;
7758 }
7759 }
7760
7761 /* below for sta mode */
7762
7763 if (pparm->algorithm == _NO_PRIVACY_) { /* clear cam entry */
7764 clear_cam_entry(padapter, pparm->id);
7765 return H2C_SUCCESS;
7766 }
7767 ctrl = BIT(15) | ((pparm->algorithm) << 2);
7768 write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
7769 pmlmeinfo->enc_algo = pparm->algorithm;
7770 return H2C_SUCCESS;
7771 }
7772
add_ba_hdl(struct adapter * padapter,unsigned char * pbuf)7773 u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
7774 {
7775 struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
7776 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7777 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7778
7779 struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
7780
7781 if (!psta)
7782 return H2C_SUCCESS;
7783
7784 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
7785 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
7786 issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
7787 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
7788 } else {
7789 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
7790 }
7791 return H2C_SUCCESS;
7792 }
7793
set_tx_beacon_cmd(struct adapter * padapter)7794 u8 set_tx_beacon_cmd(struct adapter *padapter)
7795 {
7796 struct cmd_obj *ph2c;
7797 struct Tx_Beacon_param *ptxBeacon_parm;
7798 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7799 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7800 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7801 u8 res = _SUCCESS;
7802 int len_diff = 0;
7803
7804 ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
7805 if (!ph2c) {
7806 res = _FAIL;
7807 goto exit;
7808 }
7809
7810 ptxBeacon_parm = kzalloc(sizeof(*ptxBeacon_parm), GFP_ATOMIC);
7811 if (!ptxBeacon_parm) {
7812 kfree(ph2c);
7813 res = _FAIL;
7814 goto exit;
7815 }
7816
7817 memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
7818
7819 len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs + _BEACON_IE_OFFSET_,
7820 ptxBeacon_parm->network.IELength - _BEACON_IE_OFFSET_,
7821 pmlmeinfo->hidden_ssid_mode);
7822 ptxBeacon_parm->network.IELength += len_diff;
7823
7824 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
7825
7826 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
7827
7828 exit:
7829
7830 return res;
7831 }
7832
mlme_evt_hdl(struct adapter * padapter,unsigned char * pbuf)7833 u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
7834 {
7835 u8 evt_code;
7836 u16 evt_sz;
7837 uint *peventbuf;
7838 void (*event_callback)(struct adapter *dev, u8 *pbuf);
7839 struct evt_priv *pevt_priv = &padapter->evtpriv;
7840
7841 peventbuf = (uint *)pbuf;
7842 evt_sz = (u16)(*peventbuf & 0xffff);
7843 evt_code = (u8)((*peventbuf >> 16) & 0xff);
7844
7845 /* checking if event code is valid */
7846 if (evt_code >= MAX_C2HEVT)
7847 goto _abort_event_;
7848
7849 /* checking if event size match the event parm size */
7850 if ((wlanevents[evt_code].parmsize != 0) &&
7851 (wlanevents[evt_code].parmsize != evt_sz))
7852 goto _abort_event_;
7853
7854 atomic_inc(&pevt_priv->event_seq);
7855
7856 peventbuf += 2;
7857
7858 if (peventbuf) {
7859 event_callback = wlanevents[evt_code].event_callback;
7860 event_callback(padapter, (u8 *)peventbuf);
7861 }
7862
7863 _abort_event_:
7864 return H2C_SUCCESS;
7865 }
7866
h2c_msg_hdl(struct adapter * padapter,unsigned char * pbuf)7867 u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
7868 {
7869 if (!pbuf)
7870 return H2C_PARAMETERS_ERROR;
7871
7872 return H2C_SUCCESS;
7873 }
7874
tx_beacon_hdl(struct adapter * padapter,unsigned char * pbuf)7875 u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
7876 {
7877 if (send_beacon(padapter) == _FAIL) {
7878 return H2C_PARAMETERS_ERROR;
7879 } else {
7880 /* tx bc/mc frames after update TIM */
7881 struct sta_info *psta_bmc;
7882 struct list_head *xmitframe_plist, *xmitframe_phead;
7883 struct xmit_frame *pxmitframe = NULL;
7884 struct sta_priv *pstapriv = &padapter->stapriv;
7885
7886 /* for BC/MC Frames */
7887 psta_bmc = rtw_get_bcmc_stainfo(padapter);
7888 if (!psta_bmc)
7889 return H2C_SUCCESS;
7890
7891 if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) {
7892 msleep(10);/* 10ms, ATIM(HIQ) Windows */
7893 spin_lock_bh(&psta_bmc->sleep_q.lock);
7894
7895 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
7896 xmitframe_plist = xmitframe_phead->next;
7897
7898 while (xmitframe_phead != xmitframe_plist) {
7899 pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
7900
7901 xmitframe_plist = xmitframe_plist->next;
7902
7903 list_del_init(&pxmitframe->list);
7904
7905 psta_bmc->sleepq_len--;
7906 if (psta_bmc->sleepq_len > 0)
7907 pxmitframe->attrib.mdata = 1;
7908 else
7909 pxmitframe->attrib.mdata = 0;
7910
7911 pxmitframe->attrib.triggered = 1;
7912
7913 pxmitframe->attrib.qsel = 0x11;/* HIQ */
7914
7915 spin_unlock_bh(&psta_bmc->sleep_q.lock);
7916 if (rtl8188eu_hal_xmit(padapter, pxmitframe))
7917 rtw_xmit_complete(padapter, pxmitframe);
7918 spin_lock_bh(&psta_bmc->sleep_q.lock);
7919 }
7920 spin_unlock_bh(&psta_bmc->sleep_q.lock);
7921 }
7922 }
7923 return H2C_SUCCESS;
7924 }
7925
set_ch_hdl(struct adapter * padapter,u8 * pbuf)7926 u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
7927 {
7928 struct set_ch_parm *set_ch_parm;
7929 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7930
7931 if (!pbuf)
7932 return H2C_PARAMETERS_ERROR;
7933
7934 set_ch_parm = (struct set_ch_parm *)pbuf;
7935
7936 pmlmeext->cur_channel = set_ch_parm->ch;
7937 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
7938 pmlmeext->cur_bwmode = set_ch_parm->bw;
7939
7940 set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
7941
7942 return H2C_SUCCESS;
7943 }
7944
set_chplan_hdl(struct adapter * padapter,unsigned char * pbuf)7945 u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
7946 {
7947 struct SetChannelPlan_param *setChannelPlan_param;
7948 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7949
7950 if (!pbuf)
7951 return H2C_PARAMETERS_ERROR;
7952
7953 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
7954
7955 pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
7956 init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
7957
7958 return H2C_SUCCESS;
7959 }
7960
led_blink_hdl(struct adapter * padapter,unsigned char * pbuf)7961 u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
7962 {
7963 if (!pbuf)
7964 return H2C_PARAMETERS_ERROR;
7965 return H2C_SUCCESS;
7966 }
7967
set_csa_hdl(struct adapter * padapter,unsigned char * pbuf)7968 u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
7969 {
7970 return H2C_REJECTED;
7971 }
7972
7973 /* TDLS_WRCR : write RCR DATA BIT */
7974 /* TDLS_SD_PTI : issue peer traffic indication */
7975 /* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */
7976 /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */
7977 /* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
7978 /* TDLS_OFF_CH : first time set channel to off channel */
7979 /* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */
7980 /* TDLS_P_OFF_CH : periodically go to off channel */
7981 /* TDLS_P_BASE_CH : periodically go back to base channel */
7982 /* TDLS_RS_RCR : restore RCR */
7983 /* TDLS_CKALV_PH1 : check alive timer phase1 */
7984 /* TDLS_CKALV_PH2 : check alive timer phase2 */
7985 /* TDLS_FREE_STA : free tdls sta */
tdls_hdl(struct adapter * padapter,unsigned char * pbuf)7986 u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
7987 {
7988 return H2C_REJECTED;
7989 }
7990