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