staging: rtl8723au: issue_probersp(): remove unused parameter
[linux-2.6/btrfs-unstable.git] / drivers / staging / rtl8723au / core / rtw_mlme_ext.c
blob0d7e9215cf3eed402efef6046239ada25316057f
1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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.
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.
14 ******************************************************************************/
15 #define _RTW_MLME_EXT_C_
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <wifi.h>
20 #include <rtw_mlme_ext.h>
21 #include <wlan_bssdef.h>
22 #include <mlme_osdep.h>
23 #include <recv_osdep.h>
24 #include <linux/ieee80211.h>
25 #include <rtl8723a_hal.h>
27 static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
28 static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
29 static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
30 static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
31 static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
32 static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
33 static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
34 static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
35 static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
36 static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
37 static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
39 static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
40 static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
41 static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
42 static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
43 static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
44 static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
45 static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
46 static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
48 static void issue_assocreq(struct rtw_adapter *padapter);
49 static void issue_probereq(struct rtw_adapter *padapter,
50 struct cfg80211_ssid *pssid, u8 *da);
51 static int issue_probereq_ex(struct rtw_adapter *padapter,
52 struct cfg80211_ssid *pssid,
53 u8 *da, int try_cnt, int wait_ms);
54 static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da);
55 static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
56 unsigned short status);
57 static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
58 unsigned short reason, int try_cnt, int wait_ms);
59 static void start_clnt_assoc(struct rtw_adapter *padapter);
60 static void start_clnt_auth(struct rtw_adapter *padapter);
61 static void start_clnt_join(struct rtw_adapter *padapter);
62 static void start_create_ibss(struct rtw_adapter *padapter);
63 static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
64 struct recv_frame *precv_frame);
66 #ifdef CONFIG_8723AU_AP_MODE
67 static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
68 static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
69 struct sta_info *pstat, u16 pkt_type);
70 #endif
72 static struct mlme_handler mlme_sta_tbl[]={
73 {"OnAssocReq23a", &OnAssocReq23a},
74 {"OnAssocRsp23a", &OnAssocRsp23a},
75 {"OnReAssocReq", &OnAssocReq23a},
76 {"OnReAssocRsp", &OnAssocRsp23a},
77 {"OnProbeReq23a", &OnProbeReq23a},
78 {"OnProbeRsp23a", &OnProbeRsp23a},
80 /*----------------------------------------------------------
81 below 2 are reserved
82 -----------------------------------------------------------*/
83 {"DoReserved23a", &DoReserved23a},
84 {"DoReserved23a", &DoReserved23a},
85 {"OnBeacon23a", &OnBeacon23a},
86 {"OnATIM", &OnAtim23a},
87 {"OnDisassoc23a", &OnDisassoc23a},
88 {"OnAuth23a", &OnAuth23aClient23a},
89 {"OnDeAuth23a", &OnDeAuth23a},
90 {"OnAction23a", &OnAction23a},
93 static struct action_handler OnAction23a_tbl[]={
94 {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a},
95 {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos},
96 {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls},
97 {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a},
98 {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a},
99 {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht},
100 {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a},
101 {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm},
102 {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p},
105 static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
107 /**************************************************
108 OUI definitions for the vendor specific IE
109 ***************************************************/
110 unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
111 unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
112 unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
113 unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
115 unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
116 unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
118 static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
120 /********************************************************
121 MCS rate definitions
122 *********************************************************/
123 unsigned char MCS_rate_2R23A[16] = {
124 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
125 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
126 unsigned char MCS_rate_1R23A[16] = {
127 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
128 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
130 /********************************************************
131 ChannelPlan definitions
132 *********************************************************/
134 static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
135 /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
136 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
137 /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
138 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
139 /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
140 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
141 /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
142 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
143 /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
144 {{10, 11, 12, 13}, 4},
145 /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
146 {{}, 0},
149 static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
150 /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */
151 {{}, 0},
152 /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
153 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
154 116, 120, 124, 128, 132, 136, 140}, 19},
155 /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
156 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
157 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
158 /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
159 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
160 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},
161 /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
162 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
163 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
164 /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
165 {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},
166 /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
167 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},
168 /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
169 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},
170 /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
171 {{149, 153, 157, 161, 165}, 5},
172 /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
173 {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
174 /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
175 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
176 116, 136, 140, 149, 153, 157, 161, 165}, 20},
177 /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
178 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
179 116, 120, 124, 149, 153, 157, 161, 165}, 20},
180 /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
181 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
182 116, 120, 124, 128, 132, 136, 140}, 19},
183 /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
184 {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
185 /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
186 {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},
187 /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
188 {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149,
189 153, 157, 161, 165}, 15},
190 /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
191 {{56, 60, 64, 149, 153, 157, 161, 165}, 8},
193 /* Driver self defined for old channel plan Compatible,
194 Remember to modify if have new channel plan definition ===== */
195 /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */
196 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
197 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
198 /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
199 {{36, 40, 44, 48}, 4},
200 /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
201 {{36, 40, 44, 48, 149, 153, 157, 161}, 8},
204 static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
205 /* 0x00 ~ 0x1F , Old Define ===== */
206 {0x02, 0x11}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
207 {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
208 {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
209 {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
210 {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
211 {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
212 {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
213 {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
214 {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
215 {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
216 {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
217 {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
218 {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
219 {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
220 {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
221 {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
222 {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
223 {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
224 {0x01, 0x12}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
225 {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
226 {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
227 {0x00, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
228 {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
229 {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
230 {0x05, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
231 {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
232 {0x00, 0x00}, /* 0x1A, */
233 {0x00, 0x00}, /* 0x1B, */
234 {0x00, 0x00}, /* 0x1C, */
235 {0x00, 0x00}, /* 0x1D, */
236 {0x00, 0x00}, /* 0x1E, */
237 {0x05, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
238 /* 0x20 ~ 0x7F , New Define ===== */
239 {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
240 {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
241 {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
242 {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
243 {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
244 {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
245 {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
246 {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
247 {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
248 {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
249 {0x00, 0x00}, /* 0x2A, */
250 {0x00, 0x00}, /* 0x2B, */
251 {0x00, 0x00}, /* 0x2C, */
252 {0x00, 0x00}, /* 0x2D, */
253 {0x00, 0x00}, /* 0x2E, */
254 {0x00, 0x00}, /* 0x2F, */
255 {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
256 {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
257 {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
258 {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
259 {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
260 {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
261 {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
262 {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
263 {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
264 {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
265 {0x00, 0x00}, /* 0x3A, */
266 {0x00, 0x00}, /* 0x3B, */
267 {0x00, 0x00}, /* 0x3C, */
268 {0x00, 0x00}, /* 0x3D, */
269 {0x00, 0x00}, /* 0x3E, */
270 {0x00, 0x00}, /* 0x3F, */
271 {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
272 {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
275 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE =
276 {0x03, 0x02}; /* use the conbination for max channel numbers */
278 static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf)
282 static struct fwevent wlanevents[] =
284 {0, &dummy_event_callback}, /*0*/
285 {0, NULL},
286 {0, NULL},
287 {0, NULL},
288 {0, NULL},
289 {0, NULL},
290 {0, NULL},
291 {0, NULL},
292 {0, &rtw_survey_event_cb23a}, /*8*/
293 {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a},
294 {0, &rtw23a_joinbss_event_cb}, /*10*/
295 {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
296 {sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
297 {0, &dummy_event_callback},
298 {0, &dummy_event_callback},
299 {0, NULL}, /*15*/
300 {0, NULL},
301 {0, NULL},
302 {0, NULL},
303 {0, &dummy_event_callback},
304 {0, NULL}, /*20*/
305 {0, NULL},
306 {0, NULL},
307 {0, &dummy_event_callback},
308 {0, NULL},
312 static void rtw_correct_TSF(struct rtw_adapter *padapter)
314 hw_var_set_correct_tsf(padapter);
317 static void
318 rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt)
320 pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp);
324 * Search the @param channel_num in given @param channel_set
325 * @ch_set: the given channel set
326 * @ch: the given channel number
328 * return the index of channel_num in channel_set, -1 if not found
330 int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch)
332 int i;
334 for (i = 0; ch_set[i]. ChannelNum != 0; i++) {
335 if (ch == ch_set[i].ChannelNum)
336 break;
339 if (i >= ch_set[i].ChannelNum)
340 return -1;
341 return i;
344 /****************************************************************************
346 Following are the initialization functions for WiFi MLME
348 *****************************************************************************/
350 int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
352 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
354 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
355 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
356 return _SUCCESS;
359 static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter)
361 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
362 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
363 unsigned char mixed_datarate[NumRates] = {
364 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
365 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
366 _48M_RATE_, _54M_RATE_, 0xff};
367 unsigned char mixed_basicrate[NumRates] = {
368 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
369 _12M_RATE_, _24M_RATE_, 0xff,};
371 atomic_set(&pmlmeext->event_seq, 0);
372 /* reset to zero when disconnect at client mode */
373 pmlmeext->mgnt_seq = 0;
375 pmlmeext->cur_channel = padapter->registrypriv.channel;
376 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
377 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
379 pmlmeext->retry = 0;
381 pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
383 memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
384 memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
386 if (pmlmeext->cur_channel > 14)
387 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
388 else
389 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
391 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
392 pmlmeext->sitesurvey_res.channel_idx = 0;
393 pmlmeext->sitesurvey_res.bss_cnt = 0;
394 pmlmeext->scan_abort = false;
396 pmlmeinfo->state = MSR_NOLINK;
397 pmlmeinfo->reauth_count = 0;
398 pmlmeinfo->reassoc_count = 0;
399 pmlmeinfo->link_count = 0;
400 pmlmeinfo->auth_seq = 0;
401 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
402 pmlmeinfo->key_index = 0;
403 pmlmeinfo->iv = 0;
405 pmlmeinfo->enc_algo = 0;
406 pmlmeinfo->authModeToggle = 0;
408 memset(pmlmeinfo->chg_txt, 0, 128);
410 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
411 pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
413 pmlmeinfo->dialogToken = 0;
415 pmlmeext->action_public_rxseq = 0xffff;
416 pmlmeext->action_public_dialog_token = 0xff;
419 static int has_channel(struct rt_channel_info *channel_set,
420 u8 chanset_size, u8 chan) {
421 int i;
423 for (i = 0; i < chanset_size; i++) {
424 if (channel_set[i].ChannelNum == chan)
425 return 1;
428 return 0;
431 static void init_channel_list(struct rtw_adapter *padapter,
432 struct rt_channel_info *channel_set,
433 u8 chanset_size,
434 struct p2p_channels *channel_list)
436 struct p2p_oper_class_map op_class[] = {
437 { IEEE80211G, 81, 1, 13, 1, BW20 },
438 { IEEE80211G, 82, 14, 14, 1, BW20 },
439 { IEEE80211A, 115, 36, 48, 4, BW20 },
440 { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
441 { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
442 { IEEE80211A, 124, 149, 161, 4, BW20 },
443 { IEEE80211A, 125, 149, 169, 4, BW20 },
444 { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
445 { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
446 { -1, 0, 0, 0, 0, BW20 }
449 int cla, op;
451 cla = 0;
453 for (op = 0; op_class[op].op_class; op++) {
454 u8 ch;
455 struct p2p_oper_class_map *o = &op_class[op];
456 struct p2p_reg_class *reg = NULL;
458 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
459 if (!has_channel(channel_set, chanset_size, ch))
460 continue;
462 if ((0 == padapter->registrypriv.ht_enable) &&
463 (o->inc == 8))
464 continue;
466 if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
467 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
468 continue;
470 if (reg == NULL) {
471 reg = &channel_list->reg_class[cla];
472 cla++;
473 reg->reg_class = o->op_class;
474 reg->channels = 0;
476 reg->channel[reg->channels] = ch;
477 reg->channels++;
480 channel_list->reg_classes = cla;
483 static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan,
484 struct rt_channel_info *c_set)
486 u8 i, ch_size = 0;
487 u8 b5GBand = false, b2_4GBand = false;
488 u8 Index2G = 0, Index5G = 0;
490 memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
492 if (cplan >= RT_CHANNEL_DOMAIN_MAX &&
493 cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
494 DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan);
495 return ch_size;
498 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
499 b2_4GBand = true;
500 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
501 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
502 else
503 Index2G = RTW_ChannelPlanMap[cplan].Index2G;
506 if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
507 b5GBand = true;
508 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
509 Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
510 else
511 Index5G = RTW_ChannelPlanMap[cplan].Index5G;
514 if (b2_4GBand) {
515 for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) {
516 c_set[ch_size].ChannelNum =
517 RTW_ChannelPlan2G[Index2G].Channel[i];
519 if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) ||
520 /* Channel 1~11 is active, and 12~14 is passive */
521 RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) {
522 if (c_set[ch_size].ChannelNum >= 1 &&
523 c_set[ch_size].ChannelNum <= 11)
524 c_set[ch_size].ScanType = SCAN_ACTIVE;
525 else if (c_set[ch_size].ChannelNum >= 12 &&
526 c_set[ch_size].ChannelNum <= 14)
527 c_set[ch_size].ScanType = SCAN_PASSIVE;
528 } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan ||
529 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan ||
530 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
531 /* channel 12~13, passive scan */
532 if (c_set[ch_size].ChannelNum <= 11)
533 c_set[ch_size].ScanType = SCAN_ACTIVE;
534 else
535 c_set[ch_size].ScanType = SCAN_PASSIVE;
536 } else
537 c_set[ch_size].ScanType = SCAN_ACTIVE;
539 ch_size++;
543 if (b5GBand) {
544 for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) {
545 if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 ||
546 RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) {
547 c_set[ch_size].ChannelNum =
548 RTW_ChannelPlan5G[Index5G].Channel[i];
549 if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) {
550 /* passive scan for all 5G channels */
551 c_set[ch_size].ScanType =
552 SCAN_PASSIVE;
553 } else
554 c_set[ch_size].ScanType =
555 SCAN_ACTIVE;
556 DBG_8723A("%s(): channel_set[%d].ChannelNum = "
557 "%d\n", __func__, ch_size,
558 c_set[ch_size].ChannelNum);
559 ch_size++;
564 return ch_size;
567 int init_mlme_ext_priv23a(struct rtw_adapter *padapter)
569 struct registry_priv *pregistrypriv = &padapter->registrypriv;
570 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
571 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
572 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
574 pmlmeext->padapter = padapter;
576 init_mlme_ext_priv23a_value(padapter);
577 pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
579 init_mlme_ext_timer23a(padapter);
581 #ifdef CONFIG_8723AU_AP_MODE
582 init_mlme_ap_info23a(padapter);
583 #endif
585 pmlmeext->max_chan_nums = init_channel_set(padapter,
586 pmlmepriv->ChannelPlan,
587 pmlmeext->channel_set);
588 init_channel_list(padapter, pmlmeext->channel_set,
589 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
591 pmlmeext->chan_scan_time = SURVEY_TO;
592 pmlmeext->mlmeext_init = true;
594 pmlmeext->active_keep_alive_check = true;
595 return _SUCCESS;
598 void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext)
600 struct rtw_adapter *padapter = pmlmeext->padapter;
602 if (!padapter)
603 return;
605 if (padapter->bDriverStopped == true) {
606 del_timer_sync(&pmlmeext->survey_timer);
607 del_timer_sync(&pmlmeext->link_timer);
608 /* del_timer_sync(&pmlmeext->ADDBA_timer); */
612 static void
613 _mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable,
614 struct recv_frame *precv_frame)
616 struct sk_buff *skb = precv_frame->pkt;
617 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
619 if (ptable->func) {
620 /* receive the frames that ra(a1) is my address
621 or ra(a1) is bc address. */
622 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&&
623 !is_broadcast_ether_addr(hdr->addr1))
624 return;
626 ptable->func(padapter, precv_frame);
630 void mgt_dispatcher23a(struct rtw_adapter *padapter,
631 struct recv_frame *precv_frame)
633 struct mlme_handler *ptable;
634 #ifdef CONFIG_8723AU_AP_MODE
635 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
636 #endif /* CONFIG_8723AU_AP_MODE */
637 struct sk_buff *skb = precv_frame->pkt;
638 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
639 struct sta_info *psta;
640 u16 stype;
641 int index;
643 if (!ieee80211_is_mgmt(mgmt->frame_control))
644 return;
646 /* receive the frames that ra(a1) is my address or ra(a1) is
647 bc address. */
648 if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) &&
649 !is_broadcast_ether_addr(mgmt->da))
650 return;
652 ptable = mlme_sta_tbl;
654 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
655 index = stype >> 4;
657 if (index > 13) {
658 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
659 "Currently we do not support reserved sub-fr-type =%d\n",
660 index);
661 return;
663 ptable += index;
665 psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa);
667 if (psta) {
668 if (ieee80211_has_retry(mgmt->frame_control)) {
669 if (precv_frame->attrib.seq_num ==
670 psta->RxMgmtFrameSeqNum) {
671 /* drop the duplicate management frame */
672 DBG_8723A("Drop duplicate management frame "
673 "with seq_num = %d.\n",
674 precv_frame->attrib.seq_num);
675 return;
678 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
681 #ifdef CONFIG_8723AU_AP_MODE
682 switch (stype) {
683 case IEEE80211_STYPE_AUTH:
684 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
685 ptable->func = &OnAuth23a;
686 else
687 ptable->func = &OnAuth23aClient23a;
688 /* pass through */
689 case IEEE80211_STYPE_ASSOC_REQ:
690 case IEEE80211_STYPE_REASSOC_REQ:
691 _mgt_dispatcher23a(padapter, ptable, precv_frame);
692 break;
693 case IEEE80211_STYPE_PROBE_REQ:
694 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
695 _mgt_dispatcher23a(padapter, ptable, precv_frame);
696 else
697 _mgt_dispatcher23a(padapter, ptable, precv_frame);
698 break;
699 case IEEE80211_STYPE_BEACON:
700 _mgt_dispatcher23a(padapter, ptable, precv_frame);
701 break;
702 case IEEE80211_STYPE_ACTION:
703 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
704 _mgt_dispatcher23a(padapter, ptable, precv_frame);
705 break;
706 default:
707 _mgt_dispatcher23a(padapter, ptable, precv_frame);
708 break;
710 #else
711 _mgt_dispatcher23a(padapter, ptable, precv_frame);
712 #endif
715 /****************************************************************************
717 Following are the callback functions for each subtype of the management frames
719 *****************************************************************************/
721 static int
722 OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
724 const u8 *ie;
725 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
726 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
727 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
728 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
729 struct sk_buff *skb = precv_frame->pkt;
730 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
731 int len = skb->len;
733 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
734 return _SUCCESS;
736 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
737 !check_fwstate(pmlmepriv,
738 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
739 return _SUCCESS;
741 if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) {
742 printk(KERN_WARNING "%s: Received non probe request frame\n",
743 __func__);
744 return _FAIL;
747 len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
749 ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len);
751 /* check (wildcard) SSID */
752 if (!ie)
753 goto out;
755 if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) ||
756 (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) {
757 return _SUCCESS;
760 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
761 pmlmepriv->cur_network.join_res)
762 issue_probersp(padapter, mgmt->sa);
764 out:
765 return _SUCCESS;
768 static int
769 OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
771 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
773 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
774 report_survey_event23a(padapter, precv_frame);
775 return _SUCCESS;
778 return _SUCCESS;
781 static int
782 OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
784 int cam_idx;
785 struct sta_info *psta;
786 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
787 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
788 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
789 struct sta_priv *pstapriv = &padapter->stapriv;
790 struct sk_buff *skb = precv_frame->pkt;
791 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
792 int pkt_len = skb->len;
793 struct wlan_bssid_ex *pbss;
794 int ret = _SUCCESS;
795 u8 *p, *pie;
796 int pie_len;
797 u32 ielen = 0;
799 pie = mgmt->u.beacon.variable;
800 pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
801 p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len);
802 if (p && ielen > 0) {
803 if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) {
804 /* Invalid value 0x2D is detected in Extended Supported
805 * Rates (ESR) IE. Try to fix the IE length to avoid
806 * failed Beacon parsing.
808 DBG_8723A("[WIFIDBG] Error in ESR IE is detected in "
809 "Beacon of BSSID: %pM. Fix the length of "
810 "ESR IE to avoid failed Beacon parsing.\n",
811 mgmt->bssid);
812 p[1] = ielen - 1;
816 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
817 report_survey_event23a(padapter, precv_frame);
818 return _SUCCESS;
821 if (!ether_addr_equal(mgmt->bssid,
822 get_my_bssid23a(&pmlmeinfo->network)))
823 goto out;
825 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
826 /* we should update current network before auth,
827 or some IE is wrong */
828 pbss = collect_bss_info(padapter, precv_frame);
829 if (pbss) {
830 update_network23a(&pmlmepriv->cur_network.network, pbss,
831 padapter, true);
832 rtw_get_bcn_info23a(&pmlmepriv->cur_network);
833 kfree(pbss);
836 /* check the vendor of the assoc AP */
837 pmlmeinfo->assoc_AP_vendor =
838 check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len -
839 offsetof(struct ieee80211_mgmt, u));
841 /* update TSF Value */
842 rtw_update_TSF(pmlmeext, mgmt);
844 /* start auth */
845 start_clnt_auth(padapter);
847 return _SUCCESS;
850 if (((pmlmeinfo->state & 0x03) == MSR_AP) &&
851 (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
852 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
853 if (psta) {
854 ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len);
855 if (ret != _SUCCESS) {
856 DBG_8723A_LEVEL(_drv_always_, "ap has changed, "
857 "disconnect now\n");
858 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
859 return _SUCCESS;
861 /* update WMM, ERP in the beacon */
862 /* todo: the timer is used instead of
863 the number of the beacon received */
864 if ((sta_rx_pkts(psta) & 0xf) == 0) {
865 /* DBG_8723A("update_bcn_info\n"); */
866 update_beacon23a_info(padapter, mgmt,
867 pkt_len, psta);
870 } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
871 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
872 if (psta) {
873 /* update WMM, ERP in the beacon */
874 /* todo: the timer is used instead of the
875 number of the beacon received */
876 if ((sta_rx_pkts(psta) & 0xf) == 0) {
877 /* DBG_8723A("update_bcn_info\n"); */
878 update_beacon23a_info(padapter, mgmt,
879 pkt_len, psta);
881 } else {
882 /* allocate a new CAM entry for IBSS station */
883 cam_idx = allocate_fw_sta_entry23a(padapter);
884 if (cam_idx == NUM_STA)
885 goto out;
887 /* get supported rate */
888 if (update_sta_support_rate23a(padapter, pie, pie_len,
889 cam_idx) == _FAIL) {
890 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
891 goto out;
894 /* update TSF Value */
895 rtw_update_TSF(pmlmeext, mgmt);
897 /* report sta add event */
898 report_add_sta_event23a(padapter, mgmt->sa,
899 cam_idx);
903 out:
905 return _SUCCESS;
908 #ifdef CONFIG_8723AU_AP_MODE
909 static int
910 OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
912 static struct sta_info stat;
913 struct sta_info *pstat = NULL;
914 struct sta_priv *pstapriv = &padapter->stapriv;
915 struct security_priv *psecuritypriv = &padapter->securitypriv;
916 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
917 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
918 struct sk_buff *skb = precv_frame->pkt;
919 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
920 u8 *pframe;
921 const u8 *p;
922 unsigned char *sa;
923 u16 auth_mode, seq, algorithm;
924 int status, len = skb->len;
926 if ((pmlmeinfo->state & 0x03) != MSR_AP)
927 return _FAIL;
929 DBG_8723A("+OnAuth23a\n");
931 sa = mgmt->sa;
933 auth_mode = psecuritypriv->dot11AuthAlgrthm;
935 pframe = mgmt->u.auth.variable;
936 len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable);
938 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
939 algorithm = le16_to_cpu(mgmt->u.auth.auth_alg);
941 DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
943 if (auth_mode == 2 &&
944 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 &&
945 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104)
946 auth_mode = 0;
948 /* rx a shared-key auth but shared not enabled, or */
949 /* rx a open-system auth but shared-key is enabled */
950 if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) ||
951 (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) {
952 DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib "
953 "=%d] %02X%02X%02X%02X%02X%02X\n",
954 algorithm, auth_mode,
955 sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
957 status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
959 goto auth_fail;
962 if (rtw_access_ctrl23a(padapter, sa) == false) {
963 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
964 goto auth_fail;
967 pstat = rtw_get_stainfo23a(pstapriv, sa);
968 if (!pstat) {
969 /* allocate a new one */
970 DBG_8723A("going to alloc stainfo for sa =%pM\n", sa);
971 pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC);
972 if (!pstat) {
973 DBG_8723A(" Exceed the upper limit of supported "
974 "clients...\n");
975 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
976 goto auth_fail;
979 pstat->state = WIFI_FW_AUTH_NULL;
980 pstat->auth_seq = 0;
982 /* pstat->flags = 0; */
983 /* pstat->capability = 0; */
984 } else {
985 spin_lock_bh(&pstapriv->asoc_list_lock);
986 if (!list_empty(&pstat->asoc_list)) {
987 list_del_init(&pstat->asoc_list);
988 pstapriv->asoc_list_cnt--;
989 if (pstat->expire_to > 0) {
990 /* TODO: STA re_auth within expire_to */
993 spin_unlock_bh(&pstapriv->asoc_list_lock);
995 if (seq == 1) {
996 /* TODO: STA re_auth and auth timeout */
1000 spin_lock_bh(&pstapriv->auth_list_lock);
1001 if (list_empty(&pstat->auth_list)) {
1002 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
1003 pstapriv->auth_list_cnt++;
1005 spin_unlock_bh(&pstapriv->auth_list_lock);
1007 if (pstat->auth_seq == 0)
1008 pstat->expire_to = pstapriv->auth_to;
1010 if ((pstat->auth_seq + 1) != seq) {
1011 DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, "
1012 "exp_seq =%d]!\n", seq, pstat->auth_seq+1);
1013 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1014 goto auth_fail;
1017 if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) {
1018 if (seq == 1) {
1019 pstat->state &= ~WIFI_FW_AUTH_NULL;
1020 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1021 pstat->expire_to = pstapriv->assoc_to;
1022 pstat->authalg = algorithm;
1023 } else {
1024 DBG_8723A("(2)auth rejected because out of seq "
1025 "[rx_seq =%d, exp_seq =%d]!\n",
1026 seq, pstat->auth_seq+1);
1027 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1028 goto auth_fail;
1030 } else { /* shared system or auto authentication */
1031 if (seq == 1) {
1032 /* prepare for the challenging txt... */
1033 pstat->state &= ~WIFI_FW_AUTH_NULL;
1034 pstat->state |= WIFI_FW_AUTH_STATE;
1035 pstat->authalg = algorithm;
1036 pstat->auth_seq = 2;
1037 } else if (seq == 3) {
1038 /* checking for challenging txt... */
1039 DBG_8723A("checking for challenging txt...\n");
1041 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len);
1042 if (!p || p[1] <= 0) {
1043 DBG_8723A("auth rejected because challenge "
1044 "failure!(1)\n");
1045 status = WLAN_STATUS_CHALLENGE_FAIL;
1046 goto auth_fail;
1049 if (!memcmp(p + 2, pstat->chg_txt, 128)) {
1050 pstat->state &= ~WIFI_FW_AUTH_STATE;
1051 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1052 /* challenging txt is correct... */
1053 pstat->expire_to = pstapriv->assoc_to;
1054 } else {
1055 DBG_8723A("auth rejected because challenge "
1056 "failure!\n");
1057 status = WLAN_STATUS_CHALLENGE_FAIL;
1058 goto auth_fail;
1060 } else {
1061 DBG_8723A("(3)auth rejected because out of seq "
1062 "[rx_seq =%d, exp_seq =%d]!\n",
1063 seq, pstat->auth_seq+1);
1064 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1065 goto auth_fail;
1069 /* Now, we are going to issue_auth... */
1070 pstat->auth_seq = seq + 1;
1072 issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS);
1074 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1075 pstat->auth_seq = 0;
1077 return _SUCCESS;
1079 auth_fail:
1081 if (pstat)
1082 rtw_free_stainfo23a(padapter, pstat);
1084 pstat = &stat;
1085 memset((char *)pstat, '\0', sizeof(stat));
1086 pstat->auth_seq = 2;
1087 ether_addr_copy(pstat->hwaddr, sa);
1089 issue_auth(padapter, pstat, (unsigned short)status);
1091 return _FAIL;
1093 #endif
1095 static int
1096 OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1098 unsigned int seq, status, algthm;
1099 unsigned int go2asoc = 0;
1100 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1101 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1102 struct sk_buff *skb = precv_frame->pkt;
1103 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1104 const u8 *p;
1105 u8 *pie;
1106 int plen = skb->len;
1108 DBG_8723A("%s\n", __func__);
1110 /* check A1 matches or not */
1111 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
1112 return _SUCCESS;
1114 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1115 return _SUCCESS;
1117 pie = mgmt->u.auth.variable;
1118 plen -= offsetof(struct ieee80211_mgmt, u.auth.variable);
1120 algthm = le16_to_cpu(mgmt->u.auth.auth_alg);
1121 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
1122 status = le16_to_cpu(mgmt->u.auth.status_code);
1124 if (status) {
1125 DBG_8723A("clnt auth fail, status: %d\n", status);
1126 /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
1127 if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
1128 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1129 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1130 else
1131 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1132 /* pmlmeinfo->reauth_count = 0; */
1135 set_link_timer(pmlmeext, 1);
1136 goto authclnt_fail;
1139 if (seq == 2) {
1140 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1141 /* legendary shared system */
1142 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen);
1144 if (!p) {
1145 /* DBG_8723A("marc: no challenge text?\n"); */
1146 goto authclnt_fail;
1149 memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]);
1150 pmlmeinfo->auth_seq = 3;
1151 issue_auth(padapter, NULL, 0);
1152 set_link_timer(pmlmeext, REAUTH_TO);
1154 return _SUCCESS;
1155 } else {
1156 /* open system */
1157 go2asoc = 1;
1159 } else if (seq == 4) {
1160 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1161 go2asoc = 1;
1162 else
1163 goto authclnt_fail;
1164 } else {
1165 /* this is also illegal */
1166 /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n",
1167 seq); */
1168 goto authclnt_fail;
1171 if (go2asoc) {
1172 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
1173 start_clnt_assoc(padapter);
1174 return _SUCCESS;
1177 authclnt_fail:
1179 /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1181 return _FAIL;
1184 #ifdef CONFIG_8723AU_AP_MODE
1185 static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen)
1187 unsigned int oui;
1189 /* first 3 bytes in vendor specific information element are the IEEE
1190 * OUI of the vendor. The following byte is used a vendor specific
1191 * sub-type. */
1192 if (elen < 4) {
1193 DBG_8723A("short vendor specific information element "
1194 "ignored (len =%i)\n", elen);
1195 return -EINVAL;
1198 oui = RTW_GET_BE24(pos);
1199 switch (oui) {
1200 case WLAN_OUI_MICROSOFT:
1201 /* Microsoft/Wi-Fi information elements are further typed and
1202 * subtyped */
1203 switch (pos[3]) {
1204 case WLAN_OUI_TYPE_MICROSOFT_WPA:
1205 /* Microsoft OUI (00:50:F2) with OUI Type 1:
1206 * real WPA information element */
1207 break;
1208 case WLAN_OUI_TYPE_MICROSOFT_WMM:
1209 if (elen < 5) {
1210 DBG_8723A("short WME information element "
1211 "ignored (len =%i)\n", elen);
1212 return -EINVAL;
1214 switch (pos[4]) {
1215 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
1216 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
1217 break;
1218 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
1219 break;
1220 default:
1221 DBG_8723A("unknown WME information element "
1222 "ignored (subtype =%d len =%i)\n",
1223 pos[4], elen);
1224 return -EINVAL;
1226 break;
1227 case WLAN_OUI_TYPE_MICROSOFT_WPS:
1228 /* Wi-Fi Protected Setup (WPS) IE */
1229 break;
1230 default:
1231 DBG_8723A("Unknown Microsoft information element "
1232 "ignored (type =%d len =%i)\n",
1233 pos[3], elen);
1234 return -EINVAL;
1236 break;
1238 case OUI_BROADCOM:
1239 switch (pos[3]) {
1240 case VENDOR_HT_CAPAB_OUI_TYPE:
1241 break;
1242 default:
1243 DBG_8723A("Unknown Broadcom information element "
1244 "ignored (type =%d len =%i)\n", pos[3], elen);
1245 return -EINVAL;
1247 break;
1249 default:
1250 DBG_8723A("unknown vendor specific information element "
1251 "ignored (vendor OUI %02x:%02x:%02x len =%i)\n",
1252 pos[0], pos[1], pos[2], elen);
1253 return -EINVAL;
1256 return 0;
1259 static int rtw_validate_frame_ies(const u8 *start, uint len)
1261 const u8 *pos = start;
1262 int left = len;
1263 int unknown = 0;
1265 while (left >= 2) {
1266 u8 id, elen;
1268 id = *pos++;
1269 elen = *pos++;
1270 left -= 2;
1272 if (elen > left) {
1273 DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d "
1274 "left =%i)\n", __func__, id, elen, left);
1275 return -EINVAL;
1278 switch (id) {
1279 case WLAN_EID_SSID:
1280 case WLAN_EID_SUPP_RATES:
1281 case WLAN_EID_FH_PARAMS:
1282 case WLAN_EID_DS_PARAMS:
1283 case WLAN_EID_CF_PARAMS:
1284 case WLAN_EID_TIM:
1285 case WLAN_EID_IBSS_PARAMS:
1286 case WLAN_EID_CHALLENGE:
1287 case WLAN_EID_ERP_INFO:
1288 case WLAN_EID_EXT_SUPP_RATES:
1289 break;
1290 case WLAN_EID_VENDOR_SPECIFIC:
1291 if (rtw_validate_vendor_specific_ies(pos, elen))
1292 unknown++;
1293 break;
1294 case WLAN_EID_RSN:
1295 case WLAN_EID_PWR_CAPABILITY:
1296 case WLAN_EID_SUPPORTED_CHANNELS:
1297 case WLAN_EID_MOBILITY_DOMAIN:
1298 case WLAN_EID_FAST_BSS_TRANSITION:
1299 case WLAN_EID_TIMEOUT_INTERVAL:
1300 case WLAN_EID_HT_CAPABILITY:
1301 case WLAN_EID_HT_OPERATION:
1302 default:
1303 unknown++;
1304 DBG_8723A("%s IEEE 802.11 ignored unknown element "
1305 "(id =%d elen =%d)\n", __func__, id, elen);
1306 break;
1309 left -= elen;
1310 pos += elen;
1313 if (left)
1314 return -EINVAL;
1316 return 0;
1318 #endif
1320 static int
1321 OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1323 #ifdef CONFIG_8723AU_AP_MODE
1324 u16 capab_info, listen_interval;
1325 struct sta_info *pstat;
1326 unsigned char reassoc;
1327 int i, wpa_ie_len, left;
1328 unsigned char supportRate[16];
1329 int supportRateNum;
1330 unsigned short status = WLAN_STATUS_SUCCESS;
1331 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1332 struct security_priv *psecuritypriv = &padapter->securitypriv;
1333 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1334 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1335 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
1336 struct sta_priv *pstapriv = &padapter->stapriv;
1337 struct sk_buff *skb = precv_frame->pkt;
1338 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1339 const u8 *pos, *p, *wpa_ie, *wps_ie;
1340 u8 *pframe = skb->data;
1341 uint pkt_len = skb->len;
1342 int r;
1344 if ((pmlmeinfo->state & 0x03) != MSR_AP)
1345 return _FAIL;
1347 left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
1348 if (ieee80211_is_assoc_req(mgmt->frame_control)) {
1349 reassoc = 0;
1350 pos = mgmt->u.assoc_req.variable;
1351 left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
1352 } else { /* WIFI_REASSOCREQ */
1353 reassoc = 1;
1354 pos = mgmt->u.reassoc_req.variable;
1355 left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable);
1358 if (left < 0) {
1359 DBG_8723A("handle_assoc(reassoc =%d) - too short payload "
1360 "(len =%lu)\n", reassoc, (unsigned long)pkt_len);
1361 return _FAIL;
1364 pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1365 if (!pstat) {
1366 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1367 goto asoc_class2_error;
1370 /* These two are located at the same offsets whether it's an
1371 * assoc_req or a reassoc_req */
1372 capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info);
1373 listen_interval =
1374 get_unaligned_le16(&mgmt->u.assoc_req.listen_interval);
1376 DBG_8723A("%s\n", __func__);
1378 /* check if this stat has been successfully authenticated/assocated */
1379 if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) {
1380 if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) {
1381 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1382 goto asoc_class2_error;
1383 } else {
1384 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1385 pstat->state |= WIFI_FW_ASSOC_STATE;
1387 } else {
1388 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1389 pstat->state |= WIFI_FW_ASSOC_STATE;
1392 pstat->capability = capab_info;
1394 /* now parse all ieee802_11 ie to point to elems */
1396 if (rtw_validate_frame_ies(pos, left)) {
1397 DBG_8723A("STA %pM sent invalid association request\n",
1398 pstat->hwaddr);
1399 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1400 goto OnAssocReq23aFail;
1403 /* now we should check all the fields... */
1404 /* checking SSID */
1405 p = cfg80211_find_ie(WLAN_EID_SSID, pos, left);
1406 if (!p || p[1] == 0) {
1407 /* broadcast ssid, however it is not allowed in assocreq */
1408 DBG_8723A("STA %pM sent invalid association request lacking an SSID\n",
1409 pstat->hwaddr);
1410 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1411 goto OnAssocReq23aFail;
1412 } else {
1413 /* check if ssid match */
1414 if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len))
1415 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1417 if (p[1] != cur->Ssid.ssid_len)
1418 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1421 if (status != WLAN_STATUS_SUCCESS)
1422 goto OnAssocReq23aFail;
1424 /* check if the supported rate is ok */
1425 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left);
1426 if (!p) {
1427 DBG_8723A("Rx a sta assoc-req which supported rate is "
1428 "empty!\n");
1429 /* use our own rate set as statoin used */
1430 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1431 /* supportRateNum = AP_BSSRATE_LEN; */
1433 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1434 goto OnAssocReq23aFail;
1435 } else {
1436 memcpy(supportRate, p + 2, p[1]);
1437 supportRateNum = p[1];
1439 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left);
1440 if (p) {
1441 if (supportRateNum <= sizeof(supportRate)) {
1442 memcpy(supportRate+supportRateNum, p + 2, p[1]);
1443 supportRateNum += p[1];
1448 /* todo: mask supportRate between AP & STA -> move to update raid */
1449 /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1451 /* update station supportRate */
1452 pstat->bssratelen = supportRateNum;
1453 memcpy(pstat->bssrateset, supportRate, supportRateNum);
1454 Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1456 /* check RSN/WPA/WPS */
1457 pstat->dot8021xalg = 0;
1458 pstat->wpa_psk = 0;
1459 pstat->wpa_group_cipher = 0;
1460 pstat->wpa2_group_cipher = 0;
1461 pstat->wpa_pairwise_cipher = 0;
1462 pstat->wpa2_pairwise_cipher = 0;
1463 memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1465 wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left);
1466 if (!wpa_ie)
1467 wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1468 WLAN_OUI_TYPE_MICROSOFT_WPA,
1469 pos, left);
1470 if (wpa_ie) {
1471 int group_cipher = 0, pairwise_cipher = 0;
1473 wpa_ie_len = wpa_ie[1];
1474 if (psecuritypriv->wpa_psk & BIT(1)) {
1475 r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2,
1476 &group_cipher,
1477 &pairwise_cipher, NULL);
1478 if (r == _SUCCESS) {
1479 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1480 pstat->wpa_psk |= BIT(1);
1482 pstat->wpa2_group_cipher = group_cipher &
1483 psecuritypriv->wpa2_group_cipher;
1484 pstat->wpa2_pairwise_cipher = pairwise_cipher &
1485 psecuritypriv->wpa2_pairwise_cipher;
1486 } else
1487 status = WLAN_STATUS_INVALID_IE;
1488 } else if (psecuritypriv->wpa_psk & BIT(0)) {
1489 r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2,
1490 &group_cipher, &pairwise_cipher,
1491 NULL);
1492 if (r == _SUCCESS) {
1493 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1494 pstat->wpa_psk |= BIT(0);
1496 pstat->wpa_group_cipher = group_cipher &
1497 psecuritypriv->wpa_group_cipher;
1498 pstat->wpa_pairwise_cipher = pairwise_cipher &
1499 psecuritypriv->wpa_pairwise_cipher;
1500 } else
1501 status = WLAN_STATUS_INVALID_IE;
1502 } else {
1503 wpa_ie = NULL;
1504 wpa_ie_len = 0;
1506 if (wpa_ie && status == WLAN_STATUS_SUCCESS) {
1507 if (!pstat->wpa_group_cipher)
1508 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1510 if (!pstat->wpa_pairwise_cipher)
1511 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1515 if (status != WLAN_STATUS_SUCCESS)
1516 goto OnAssocReq23aFail;
1518 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1520 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1521 WLAN_OUI_TYPE_MICROSOFT_WPS,
1522 pos, left);
1524 if (!wpa_ie) {
1525 if (wps_ie) {
1526 DBG_8723A("STA included WPS IE in (Re)Association "
1527 "Request - assume WPS is used\n");
1528 pstat->flags |= WLAN_STA_WPS;
1529 } else {
1530 DBG_8723A("STA did not include WPA/RSN IE in (Re)"
1531 "Association Request - possible WPS use\n");
1532 pstat->flags |= WLAN_STA_MAYBE_WPS;
1534 } else {
1535 int copy_len;
1537 if (psecuritypriv->wpa_psk == 0) {
1538 DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
1539 pstat->hwaddr);
1541 status = WLAN_STATUS_INVALID_IE;
1543 goto OnAssocReq23aFail;
1546 if (wps_ie) {
1547 DBG_8723A("STA included WPS IE in (Re)Association "
1548 "Request - WPS is used\n");
1549 pstat->flags |= WLAN_STA_WPS;
1550 copy_len = 0;
1551 } else {
1552 copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ?
1553 sizeof(pstat->wpa_ie) : (wpa_ie_len + 2);
1556 if (copy_len > 0)
1557 memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
1560 /* check if there is WMM IE & support WWM-PS */
1561 pstat->flags &= ~WLAN_STA_WME;
1562 pstat->qos_option = 0;
1563 pstat->qos_info = 0;
1564 pstat->has_legacy_ac = true;
1565 pstat->uapsd_vo = 0;
1566 pstat->uapsd_vi = 0;
1567 pstat->uapsd_be = 0;
1568 pstat->uapsd_bk = 0;
1569 if (pmlmepriv->qos_option) {
1570 const u8 *end = pos + left;
1572 p = pos;
1574 for (;;) {
1575 left = end - p;
1576 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1577 WLAN_OUI_TYPE_MICROSOFT_WMM,
1578 p, left);
1579 if (p) {
1580 pstat->flags |= WLAN_STA_WME;
1582 pstat->qos_option = 1;
1583 pstat->qos_info = *(p + 8);
1585 pstat->max_sp_len =
1586 (pstat->qos_info >> 5) & 0x3;
1588 if ((pstat->qos_info & 0xf) != 0xf)
1589 pstat->has_legacy_ac = true;
1590 else
1591 pstat->has_legacy_ac = false;
1593 if (pstat->qos_info & 0xf) {
1594 if (pstat->qos_info & BIT(0))
1595 pstat->uapsd_vo = BIT(0)|BIT(1);
1596 else
1597 pstat->uapsd_vo = 0;
1599 if (pstat->qos_info & BIT(1))
1600 pstat->uapsd_vi = BIT(0)|BIT(1);
1601 else
1602 pstat->uapsd_vi = 0;
1604 if (pstat->qos_info & BIT(2))
1605 pstat->uapsd_bk = BIT(0)|BIT(1);
1606 else
1607 pstat->uapsd_bk = 0;
1609 if (pstat->qos_info & BIT(3))
1610 pstat->uapsd_be = BIT(0)|BIT(1);
1611 else
1612 pstat->uapsd_be = 0;
1614 break;
1616 } else {
1617 break;
1619 p = p + p[1] + 2;
1623 /* save HT capabilities in the sta object */
1624 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1625 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left);
1627 if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) {
1628 pstat->flags |= WLAN_STA_HT;
1630 pstat->flags |= WLAN_STA_WME;
1632 memcpy(&pstat->htpriv.ht_cap, p + 2,
1633 sizeof(struct ieee80211_ht_cap));
1634 } else
1635 pstat->flags &= ~WLAN_STA_HT;
1637 if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){
1638 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1639 goto OnAssocReq23aFail;
1642 if (pstat->flags & WLAN_STA_HT &&
1643 (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP ||
1644 pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
1645 DBG_8723A("HT: %pM tried to use TKIP with HT association\n",
1646 pstat->hwaddr);
1648 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1649 /* goto OnAssocReq23aFail; */
1652 pstat->flags |= WLAN_STA_NONERP;
1653 for (i = 0; i < pstat->bssratelen; i++) {
1654 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1655 pstat->flags &= ~WLAN_STA_NONERP;
1656 break;
1660 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1661 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1662 else
1663 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1665 if (status != WLAN_STATUS_SUCCESS)
1666 goto OnAssocReq23aFail;
1668 /* TODO: identify_proprietary_vendor_ie(); */
1669 /* Realtek proprietary IE */
1670 /* identify if this is Broadcom sta */
1671 /* identify if this is ralink sta */
1672 /* Customer proprietary IE */
1674 /* get a unique AID */
1675 if (pstat->aid > 0) {
1676 DBG_8723A(" old AID %d\n", pstat->aid);
1677 } else {
1678 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1679 if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1680 break;
1682 if (pstat->aid > NUM_STA)
1683 pstat->aid = NUM_STA;
1684 if (pstat->aid > pstapriv->max_num_sta) {
1686 pstat->aid = 0;
1688 DBG_8723A(" no room for more AIDs\n");
1690 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1692 goto OnAssocReq23aFail;
1693 } else {
1694 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1695 DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
1699 pstat->state &= ~WIFI_FW_ASSOC_STATE;
1700 pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1702 spin_lock_bh(&pstapriv->auth_list_lock);
1703 if (!list_empty(&pstat->auth_list)) {
1704 list_del_init(&pstat->auth_list);
1705 pstapriv->auth_list_cnt--;
1707 spin_unlock_bh(&pstapriv->auth_list_lock);
1709 spin_lock_bh(&pstapriv->asoc_list_lock);
1710 if (list_empty(&pstat->asoc_list)) {
1711 pstat->expire_to = pstapriv->expire_to;
1712 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1713 pstapriv->asoc_list_cnt++;
1715 spin_unlock_bh(&pstapriv->asoc_list_lock);
1717 /* now the station is qualified to join our BSS... */
1718 if (pstat && pstat->state & WIFI_FW_ASSOC_SUCCESS &&
1719 status == WLAN_STATUS_SUCCESS) {
1720 #ifdef CONFIG_8723AU_AP_MODE
1721 /* 1 bss_cap_update & sta_info_update23a */
1722 bss_cap_update_on_sta_join23a(padapter, pstat);
1723 sta_info_update23a(padapter, pstat);
1725 /* issue assoc rsp before notify station join event. */
1726 if (ieee80211_is_assoc_req(mgmt->frame_control))
1727 issue_assocrsp(padapter, status, pstat,
1728 IEEE80211_STYPE_ASSOC_RESP);
1729 else
1730 issue_assocrsp(padapter, status, pstat,
1731 IEEE80211_STYPE_REASSOC_RESP);
1733 /* 2 - report to upper layer */
1734 DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
1735 rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1737 /* 3-(1) report sta add event */
1738 report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid);
1739 #endif
1742 return _SUCCESS;
1744 asoc_class2_error:
1746 #ifdef CONFIG_8723AU_AP_MODE
1747 issue_deauth23a(padapter, mgmt->sa, status);
1748 #endif
1749 return _FAIL;
1751 OnAssocReq23aFail:
1753 #ifdef CONFIG_8723AU_AP_MODE
1754 pstat->aid = 0;
1755 if (ieee80211_is_assoc_req(mgmt->frame_control))
1756 issue_assocrsp(padapter, status, pstat,
1757 IEEE80211_STYPE_ASSOC_RESP);
1758 else
1759 issue_assocrsp(padapter, status, pstat,
1760 IEEE80211_STYPE_REASSOC_RESP);
1761 #endif
1763 #endif /* CONFIG_8723AU_AP_MODE */
1765 return _FAIL;
1768 static int
1769 OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1771 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1772 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1773 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1774 struct sk_buff *skb = precv_frame->pkt;
1775 struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
1776 int res;
1777 unsigned short status;
1778 const u8 *p, *pie;
1779 u8 *pframe = skb->data;
1780 int pkt_len = skb->len;
1781 int pielen;
1783 DBG_8723A("%s\n", __func__);
1785 /* check A1 matches or not */
1786 if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da))
1787 return _SUCCESS;
1789 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1790 return _SUCCESS;
1792 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1793 return _SUCCESS;
1795 del_timer_sync(&pmlmeext->link_timer);
1797 /* status */
1798 status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
1799 if (status > 0) {
1800 DBG_8723A("assoc reject, status code: %d\n", status);
1801 pmlmeinfo->state = MSR_NOLINK;
1802 res = -4;
1803 goto report_assoc_result;
1806 /* get capabilities */
1807 pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info);
1809 /* set slot time */
1810 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
1812 /* AID */
1813 res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
1815 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1816 pielen = pkt_len -
1817 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1819 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
1820 pmgmt->u.assoc_resp.variable, pielen);
1821 if (p && p[1])
1822 HT_caps_handler23a(padapter, p);
1824 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
1825 pmgmt->u.assoc_resp.variable, pielen);
1826 if (p && p[1])
1827 HT_info_handler23a(padapter, p);
1829 p = cfg80211_find_ie(WLAN_EID_ERP_INFO,
1830 pmgmt->u.assoc_resp.variable, pielen);
1831 if (p && p[1])
1832 ERP_IE_handler23a(padapter, p);
1834 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1835 while (true) {
1836 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1837 WLAN_OUI_TYPE_MICROSOFT_WMM,
1838 pie, pframe + pkt_len - pie);
1839 if (!p)
1840 break;
1842 pie = p + p[1] + 2;
1843 /* if this IE is too short, try the next */
1844 if (p[1] <= 4)
1845 continue;
1846 /* if this IE is WMM params, we found what we wanted */
1847 if (p[6] == 1)
1848 break;
1851 if (p && p[1])
1852 WMM_param_handler23a(padapter, p);
1854 pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
1855 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1857 /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1858 UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates);
1860 report_assoc_result:
1861 pmlmepriv->assoc_rsp_len = 0;
1862 if (res > 0) {
1863 kfree(pmlmepriv->assoc_rsp);
1864 pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC);
1865 if (pmlmepriv->assoc_rsp) {
1866 memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len);
1867 pmlmepriv->assoc_rsp_len = pkt_len;
1869 } else
1870 kfree(pmlmepriv->assoc_rsp);
1872 report_join_res23a(padapter, res);
1874 return _SUCCESS;
1877 static int
1878 OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1880 unsigned short reason;
1881 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1882 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1883 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1884 struct sk_buff *skb = precv_frame->pkt;
1885 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1887 if (!ether_addr_equal(mgmt->bssid,
1888 get_my_bssid23a(&pmlmeinfo->network)))
1889 return _SUCCESS;
1891 reason = le16_to_cpu(mgmt->u.deauth.reason_code);
1893 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1895 #ifdef CONFIG_8723AU_AP_MODE
1896 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1897 struct sta_info *psta;
1898 struct sta_priv *pstapriv = &padapter->stapriv;
1900 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
1901 "sta:%pM\n", reason, mgmt->sa);
1903 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1904 if (psta) {
1905 u8 updated = 0;
1907 spin_lock_bh(&pstapriv->asoc_list_lock);
1908 if (!list_empty(&psta->asoc_list)) {
1909 list_del_init(&psta->asoc_list);
1910 pstapriv->asoc_list_cnt--;
1911 updated = ap_free_sta23a(padapter, psta,
1912 false, reason);
1914 spin_unlock_bh(&pstapriv->asoc_list_lock);
1916 associated_clients_update23a(padapter, updated);
1919 return _SUCCESS;
1920 } else
1921 #endif
1923 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
1924 "sta:%pM\n", reason, mgmt->bssid);
1926 receive_disconnect23a(padapter, mgmt->bssid, reason);
1928 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1930 return _SUCCESS;
1933 static int
1934 OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1936 unsigned short reason;
1937 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1938 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1939 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1940 struct sk_buff *skb = precv_frame->pkt;
1941 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1943 if (!ether_addr_equal(mgmt->bssid,
1944 get_my_bssid23a(&pmlmeinfo->network)))
1945 return _SUCCESS;
1947 reason = le16_to_cpu(mgmt->u.disassoc.reason_code);
1949 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1951 #ifdef CONFIG_8723AU_AP_MODE
1952 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1953 struct sta_info *psta;
1954 struct sta_priv *pstapriv = &padapter->stapriv;
1956 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
1957 " sta:%pM\n", reason, mgmt->sa);
1959 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1960 if (psta) {
1961 u8 updated = 0;
1963 spin_lock_bh(&pstapriv->asoc_list_lock);
1964 if (!list_empty(&psta->asoc_list)) {
1965 list_del_init(&psta->asoc_list);
1966 pstapriv->asoc_list_cnt--;
1967 updated = ap_free_sta23a(padapter, psta,
1968 false, reason);
1970 spin_unlock_bh(&pstapriv->asoc_list_lock);
1972 associated_clients_update23a(padapter, updated);
1975 return _SUCCESS;
1976 } else
1977 #endif
1979 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
1980 "code(%d) sta:%pM\n", reason, mgmt->bssid);
1982 receive_disconnect23a(padapter, mgmt->bssid, reason);
1984 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1985 return _SUCCESS;
1988 static int
1989 OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1991 DBG_8723A("%s\n", __func__);
1992 return _SUCCESS;
1995 static int
1996 on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1998 return _FAIL;
2001 static int
2002 OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2004 return _SUCCESS;
2007 static int
2008 OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2010 return _SUCCESS;
2013 static int OnAction23a_back23a(struct rtw_adapter *padapter,
2014 struct recv_frame *precv_frame)
2016 u8 *addr;
2017 struct sta_info *psta = NULL;
2018 struct recv_reorder_ctrl *preorder_ctrl;
2019 unsigned char category, action;
2020 unsigned short tid, status, capab, params, reason_code = 0;
2021 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2022 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2023 struct sk_buff *skb = precv_frame->pkt;
2024 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2025 struct sta_priv *pstapriv = &padapter->stapriv;
2027 /* check RA matches or not */
2028 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
2029 return _SUCCESS;
2031 DBG_8723A("%s\n", __func__);
2033 if ((pmlmeinfo->state&0x03) != MSR_AP)
2034 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2035 return _SUCCESS;
2037 addr = mgmt->sa;
2038 psta = rtw_get_stainfo23a(pstapriv, addr);
2040 if (!psta)
2041 return _SUCCESS;
2043 category = mgmt->u.action.category;
2044 if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */
2045 if (!pmlmeinfo->HT_enable)
2046 return _SUCCESS;
2047 /* action_code is located in the same place for all
2048 action events, so pick any */
2049 action = mgmt->u.action.u.wme_action.action_code;
2050 DBG_8723A("%s, action =%d\n", __func__, action);
2051 switch (action) {
2052 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
2053 memcpy(&pmlmeinfo->ADDBA_req,
2054 &mgmt->u.action.u.addba_req.dialog_token,
2055 sizeof(struct ADDBA_request));
2056 process_addba_req23a(padapter,
2057 (u8 *)&pmlmeinfo->ADDBA_req, addr);
2058 if (pmlmeinfo->bAcceptAddbaReq == true)
2059 issue_action_BA23a(padapter, addr,
2060 WLAN_ACTION_ADDBA_RESP, 0);
2061 else {
2062 /* reject ADDBA Req */
2063 issue_action_BA23a(padapter, addr,
2064 WLAN_ACTION_ADDBA_RESP, 37);
2066 break;
2067 case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
2068 status = get_unaligned_le16(
2069 &mgmt->u.action.u.addba_resp.status);
2070 capab = get_unaligned_le16(
2071 &mgmt->u.action.u.addba_resp.capab);
2072 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
2073 if (status == 0) { /* successful */
2074 DBG_8723A("agg_enable for TID =%d\n", tid);
2075 psta->htpriv.agg_enable_bitmap |= BIT(tid);
2076 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2077 } else
2078 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2079 break;
2081 case WLAN_ACTION_DELBA: /* DELBA */
2082 params = get_unaligned_le16(
2083 &mgmt->u.action.u.delba.params);
2084 tid = params >> 12;
2086 if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
2087 preorder_ctrl = &psta->recvreorder_ctrl[tid];
2088 preorder_ctrl->enable = false;
2089 preorder_ctrl->indicate_seq = 0xffff;
2090 } else {
2091 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2092 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2094 reason_code = get_unaligned_le16(
2095 &mgmt->u.action.u.delba.reason_code);
2096 /* todo: how to notify the host while receiving
2097 DELETE BA */
2098 break;
2099 default:
2100 break;
2103 return _SUCCESS;
2106 static int on_action_public23a(struct rtw_adapter *padapter,
2107 struct recv_frame *precv_frame)
2109 struct sk_buff *skb = precv_frame->pkt;
2110 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2111 u8 *pframe = skb->data;
2112 int freq, channel;
2114 /* check RA matches or not */
2115 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
2116 return _FAIL;
2118 channel = rtw_get_oper_ch23a(padapter);
2120 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2121 freq = ieee80211_channel_to_frequency(channel,
2122 IEEE80211_BAND_2GHZ);
2123 else
2124 freq = ieee80211_channel_to_frequency(channel,
2125 IEEE80211_BAND_5GHZ);
2127 if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
2128 skb->len, 0))
2129 return _SUCCESS;
2131 return _FAIL;
2134 static int
2135 OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2137 return _SUCCESS;
2140 static int
2141 OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2143 return _SUCCESS;
2146 static int
2147 OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2149 return _SUCCESS;
2152 static int
2153 OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2155 int i;
2156 u8 category;
2157 struct action_handler *ptable;
2158 struct sk_buff *skb = precv_frame->pkt;
2159 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2161 category = mgmt->u.action.category;
2163 for (i = 0;
2164 i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) {
2165 ptable = &OnAction23a_tbl[i];
2167 if (category == ptable->num)
2168 ptable->func(padapter, precv_frame);
2171 return _SUCCESS;
2174 static int DoReserved23a(struct rtw_adapter *padapter,
2175 struct recv_frame *precv_frame)
2177 return _SUCCESS;
2180 struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
2182 struct xmit_frame *pmgntframe;
2183 struct xmit_buf *pxmitbuf;
2185 pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
2187 if (!pmgntframe) {
2188 DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__,
2189 pxmitpriv->adapter->pnetdev->name);
2190 goto exit;
2193 pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
2194 if (!pxmitbuf) {
2195 DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__,
2196 pxmitpriv->adapter->pnetdev->name);
2197 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
2198 pmgntframe = NULL;
2199 goto exit;
2202 pmgntframe->frame_tag = MGNT_FRAMETAG;
2203 pmgntframe->pxmitbuf = pxmitbuf;
2204 pmgntframe->buf_addr = pxmitbuf->pbuf;
2205 pxmitbuf->priv_data = pmgntframe;
2207 exit:
2208 return pmgntframe;
2211 /****************************************************************************
2213 Following are some TX functions for WiFi MLME
2215 *****************************************************************************/
2217 void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
2219 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2221 pmlmeext->tx_rate = rate;
2222 DBG_8723A("%s(): rate = %x\n", __func__, rate);
2225 void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
2226 struct pkt_attrib *pattrib)
2228 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2230 memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
2232 pattrib->hdrlen = 24;
2233 pattrib->nr_frags = 1;
2234 pattrib->priority = 7;
2235 pattrib->mac_id = 0;
2236 pattrib->qsel = 0x12;
2238 pattrib->pktlen = 0;
2240 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
2241 pattrib->raid = 6;/* b mode */
2242 else
2243 pattrib->raid = 5;/* a/g mode */
2245 pattrib->encrypt = 0;
2246 pattrib->bswenc = false;
2248 pattrib->qos_en = false;
2249 pattrib->ht_en = false;
2250 pattrib->bwmode = HT_CHANNEL_WIDTH_20;
2251 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2252 pattrib->sgi = false;
2254 pattrib->seqnum = pmlmeext->mgnt_seq;
2256 pattrib->retry_ctrl = true;
2259 void dump_mgntframe23a(struct rtw_adapter *padapter,
2260 struct xmit_frame *pmgntframe)
2262 if (padapter->bSurpriseRemoved == true ||
2263 padapter->bDriverStopped == true)
2264 return;
2266 rtl8723au_mgnt_xmit(padapter, pmgntframe);
2269 int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
2270 struct xmit_frame *pmgntframe, int timeout_ms)
2272 int ret = _FAIL;
2273 unsigned long irqL;
2274 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2275 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2276 struct submit_ctx sctx;
2278 if (padapter->bSurpriseRemoved == true ||
2279 padapter->bDriverStopped == true)
2280 return ret;
2282 rtw_sctx_init23a(&sctx, timeout_ms);
2283 pxmitbuf->sctx = &sctx;
2285 ret = rtl8723au_mgnt_xmit(padapter, pmgntframe);
2287 if (ret == _SUCCESS)
2288 ret = rtw_sctx_wait23a(&sctx);
2290 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2291 pxmitbuf->sctx = NULL;
2292 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2294 return ret;
2297 int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
2298 struct xmit_frame *pmgntframe)
2300 int ret = _FAIL;
2301 u32 timeout_ms = 500;/* 500ms */
2302 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2304 if (padapter->bSurpriseRemoved == true ||
2305 padapter->bDriverStopped == true)
2306 return _FAIL;
2308 mutex_lock(&pxmitpriv->ack_tx_mutex);
2309 pxmitpriv->ack_tx = true;
2311 pmgntframe->ack_report = 1;
2312 if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2313 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
2315 pxmitpriv->ack_tx = false;
2316 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2318 return ret;
2321 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2323 u8 *ssid_ie;
2324 int ssid_len_ori;
2325 int len_diff = 0;
2326 u8 *next_ie;
2327 u32 remain_len;
2329 ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
2331 /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n",
2332 __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
2334 if (ssid_ie && ssid_len_ori > 0) {
2335 switch (hidden_ssid_mode) {
2336 case 1:
2337 next_ie = ssid_ie + 2 + ssid_len_ori;
2338 remain_len = ies_len -(next_ie-ies);
2340 ssid_ie[1] = 0;
2341 memcpy(ssid_ie+2, next_ie, remain_len);
2342 len_diff -= ssid_len_ori;
2344 break;
2345 case 2:
2346 memset(&ssid_ie[2], 0, ssid_len_ori);
2347 break;
2348 default:
2349 break;
2353 return len_diff;
2356 void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
2358 struct xmit_frame *pmgntframe;
2359 struct pkt_attrib *pattrib;
2360 unsigned char *pframe;
2361 struct ieee80211_mgmt *mgmt;
2362 unsigned int rate_len;
2363 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2364 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2365 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2366 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2367 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2368 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2369 const u8 *wps_ie;
2370 u8 sr = 0;
2371 int len_diff;
2373 /* DBG_8723A("%s\n", __func__); */
2375 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2376 if (!pmgntframe) {
2377 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2378 return;
2380 #ifdef CONFIG_8723AU_AP_MODE
2381 spin_lock_bh(&pmlmepriv->bcn_update_lock);
2382 #endif
2384 /* update attribute */
2385 pattrib = &pmgntframe->attrib;
2386 update_mgntframe_attrib23a(padapter, pattrib);
2387 pattrib->qsel = 0x10;
2389 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2391 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2392 mgmt = (struct ieee80211_mgmt *)pframe;
2394 mgmt->frame_control =
2395 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
2396 mgmt->seq_ctrl = 0;
2398 ether_addr_copy(mgmt->da, bc_addr);
2399 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2400 ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
2402 /* timestamp will be inserted by hardware */
2404 put_unaligned_le16(cur_network->beacon_interval,
2405 &mgmt->u.beacon.beacon_int);
2407 put_unaligned_le16(cur_network->capability,
2408 &mgmt->u.beacon.capab_info);
2410 pframe = mgmt->u.beacon.variable;
2411 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
2413 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2414 u8 *iebuf;
2415 int buflen;
2416 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
2417 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2418 len_diff = update_hidden_ssid(pframe, cur_network->IELength,
2419 pmlmeinfo->hidden_ssid_mode);
2420 pframe += (cur_network->IELength+len_diff);
2421 pattrib->pktlen += (cur_network->IELength+len_diff);
2423 iebuf = mgmt->u.beacon.variable;
2424 buflen = pattrib->pktlen -
2425 offsetof(struct ieee80211_mgmt, u.beacon.variable);
2426 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2427 WLAN_OUI_TYPE_MICROSOFT_WPS,
2428 iebuf, buflen);
2430 if (wps_ie && wps_ie[1] > 0) {
2431 rtw_get_wps_attr_content23a(wps_ie, wps_ie[1],
2432 WPS_ATTR_SELECTED_REGISTRAR,
2433 (u8 *)&sr);
2435 if (sr != 0)
2436 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2437 else
2438 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2440 goto _issue_bcn;
2443 /* SSID */
2444 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2445 cur_network->Ssid.ssid_len,
2446 cur_network->Ssid.ssid, &pattrib->pktlen);
2448 /* supported rates... */
2449 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2450 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2451 ((rate_len > 8)? 8: rate_len),
2452 cur_network->SupportedRates, &pattrib->pktlen);
2454 /* DS parameter set */
2455 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
2456 &cur_network->DSConfig, &pattrib->pktlen);
2458 /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */
2460 u8 erpinfo = 0;
2461 u32 ATIMWindow;
2462 /* IBSS Parameter Set... */
2463 /* ATIMWindow = cur->ATIMWindow; */
2464 ATIMWindow = 0;
2465 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2466 (unsigned char *)&ATIMWindow,
2467 &pattrib->pktlen);
2469 /* ERP IE */
2470 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2471 &erpinfo, &pattrib->pktlen);
2474 /* EXTERNDED SUPPORTED RATE */
2475 if (rate_len > 8)
2476 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2477 rate_len - 8,
2478 cur_network->SupportedRates + 8,
2479 &pattrib->pktlen);
2481 /* todo:HT for adhoc */
2483 _issue_bcn:
2485 #ifdef CONFIG_8723AU_AP_MODE
2486 pmlmepriv->update_bcn = false;
2488 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2489 #endif
2491 if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
2492 DBG_8723A("beacon frame too large\n");
2493 return;
2496 pattrib->last_txcmdsz = pattrib->pktlen;
2498 /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
2499 if (timeout_ms > 0)
2500 dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
2501 else
2502 dump_mgntframe23a(padapter, pmgntframe);
2505 static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da)
2507 struct xmit_frame *pmgntframe;
2508 struct pkt_attrib *pattrib;
2509 unsigned char *pframe;
2510 struct ieee80211_mgmt *mgmt;
2511 unsigned char *mac, *bssid;
2512 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2513 #ifdef CONFIG_8723AU_AP_MODE
2514 const u8 *pwps_ie;
2515 u8 *ssid_ie;
2516 int ssid_ielen;
2517 int ssid_ielen_diff;
2518 u8 buf[MAX_IE_SZ];
2519 #endif
2520 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2521 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2522 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2523 unsigned int rate_len;
2525 /* DBG_8723A("%s\n", __func__); */
2527 if (cur_network->IELength > MAX_IE_SZ)
2528 return;
2530 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2531 if (!pmgntframe) {
2532 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2533 return;
2536 /* update attribute */
2537 pattrib = &pmgntframe->attrib;
2538 update_mgntframe_attrib23a(padapter, pattrib);
2540 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2542 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
2543 mgmt = (struct ieee80211_mgmt *)pframe;
2545 mac = myid(&padapter->eeprompriv);
2546 bssid = cur_network->MacAddress;
2548 mgmt->frame_control =
2549 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
2551 ether_addr_copy(mgmt->da, da);
2552 ether_addr_copy(mgmt->sa, mac);
2553 ether_addr_copy(mgmt->bssid, bssid);
2555 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2556 pmlmeext->mgnt_seq++;
2558 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2560 /* timestamp will be inserted by hardware */
2561 put_unaligned_le16(cur_network->beacon_interval,
2562 &mgmt->u.probe_resp.beacon_int);
2564 put_unaligned_le16(cur_network->capability,
2565 &mgmt->u.probe_resp.capab_info);
2567 pframe = mgmt->u.probe_resp.variable;
2568 pattrib->pktlen =
2569 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
2571 /* below for ad-hoc mode */
2573 #ifdef CONFIG_8723AU_AP_MODE
2574 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2575 pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2576 WLAN_OUI_TYPE_MICROSOFT_WPS,
2577 cur_network->IEs,
2578 cur_network->IELength);
2580 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2581 pframe += cur_network->IELength;
2582 pattrib->pktlen += cur_network->IELength;
2584 /* retrieve SSID IE from cur_network->Ssid */
2586 ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable,
2587 WLAN_EID_SSID, &ssid_ielen,
2588 pframe - mgmt->u.probe_resp.variable);
2590 ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
2592 if (ssid_ie && cur_network->Ssid.ssid_len) {
2593 uint remainder_ielen;
2594 u8 *remainder_ie;
2596 remainder_ie = ssid_ie + 2;
2598 remainder_ielen = pframe - remainder_ie;
2600 DBG_8723A_LEVEL(_drv_warning_, "%s(%s): "
2601 "remainder_ielen > MAX_IE_SZ\n",
2602 __func__, padapter->pnetdev->name);
2603 if (remainder_ielen > MAX_IE_SZ)
2604 remainder_ielen = MAX_IE_SZ;
2606 memcpy(buf, remainder_ie, remainder_ielen);
2607 memcpy(remainder_ie + ssid_ielen_diff, buf,
2608 remainder_ielen);
2609 *(ssid_ie + 1) = cur_network->Ssid.ssid_len;
2610 memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
2611 cur_network->Ssid.ssid_len);
2613 pframe += ssid_ielen_diff;
2614 pattrib->pktlen += ssid_ielen_diff;
2616 } else
2617 #endif
2619 /* SSID */
2620 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2621 cur_network->Ssid.ssid_len,
2622 cur_network->Ssid.ssid,
2623 &pattrib->pktlen);
2625 /* supported rates... */
2626 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2627 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2628 ((rate_len > 8)? 8: rate_len),
2629 cur_network->SupportedRates,
2630 &pattrib->pktlen);
2632 /* DS parameter set */
2633 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
2634 (unsigned char *)&cur_network->DSConfig,
2635 &pattrib->pktlen);
2637 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
2638 u8 erpinfo = 0;
2639 u32 ATIMWindow;
2640 /* IBSS Parameter Set... */
2641 /* ATIMWindow = cur->ATIMWindow; */
2642 ATIMWindow = 0;
2643 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2644 (unsigned char *)&ATIMWindow,
2645 &pattrib->pktlen);
2647 /* ERP IE */
2648 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2649 &erpinfo, &pattrib->pktlen);
2652 /* EXTERNDED SUPPORTED RATE */
2653 if (rate_len > 8)
2654 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2655 rate_len - 8,
2656 cur_network->SupportedRates + 8,
2657 &pattrib->pktlen);
2659 /* todo:HT for adhoc */
2662 pattrib->last_txcmdsz = pattrib->pktlen;
2664 dump_mgntframe23a(padapter, pmgntframe);
2666 return;
2669 static int _issue_probereq(struct rtw_adapter *padapter,
2670 struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
2672 int ret = _FAIL;
2673 struct xmit_frame *pmgntframe;
2674 struct pkt_attrib *pattrib;
2675 unsigned char *pframe;
2676 struct ieee80211_hdr *pwlanhdr;
2677 unsigned char *mac;
2678 unsigned char bssrate[NumRates];
2679 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2680 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2681 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2682 int bssrate_len = 0;
2683 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2685 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2686 "+%s\n", __func__);
2688 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2689 if (!pmgntframe)
2690 goto exit;
2692 /* update attribute */
2693 pattrib = &pmgntframe->attrib;
2694 update_mgntframe_attrib23a(padapter, pattrib);
2696 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2698 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2699 pwlanhdr = (struct ieee80211_hdr *)pframe;
2701 mac = myid(&padapter->eeprompriv);
2703 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2704 IEEE80211_STYPE_PROBE_REQ);
2706 if (da) {
2707 /* unicast probe request frame */
2708 ether_addr_copy(pwlanhdr->addr1, da);
2709 ether_addr_copy(pwlanhdr->addr3, da);
2710 } else {
2711 /* broadcast probe request frame */
2712 ether_addr_copy(pwlanhdr->addr1, bc_addr);
2713 ether_addr_copy(pwlanhdr->addr3, bc_addr);
2716 ether_addr_copy(pwlanhdr->addr2, mac);
2718 pwlanhdr->seq_ctrl =
2719 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2721 pmlmeext->mgnt_seq++;
2723 pframe += sizeof (struct ieee80211_hdr_3addr);
2724 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
2726 if (pssid)
2727 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
2728 pssid->ssid, &pattrib->pktlen);
2729 else
2730 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
2731 &pattrib->pktlen);
2733 get_rate_set23a(padapter, bssrate, &bssrate_len);
2735 if (bssrate_len > 8) {
2736 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
2737 bssrate, &pattrib->pktlen);
2738 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2739 (bssrate_len - 8), (bssrate + 8),
2740 &pattrib->pktlen);
2741 } else {
2742 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2743 bssrate_len, bssrate, &pattrib->pktlen);
2746 /* add wps_ie for wps2.0 */
2747 if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
2748 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
2749 pmlmepriv->wps_probe_req_ie_len);
2750 pframe += pmlmepriv->wps_probe_req_ie_len;
2751 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2754 pattrib->last_txcmdsz = pattrib->pktlen;
2756 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2757 "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz);
2759 if (wait_ack) {
2760 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
2761 } else {
2762 dump_mgntframe23a(padapter, pmgntframe);
2763 ret = _SUCCESS;
2766 exit:
2767 return ret;
2770 static inline void issue_probereq(struct rtw_adapter *padapter,
2771 struct cfg80211_ssid *pssid, u8 *da)
2773 _issue_probereq(padapter, pssid, da, false);
2776 static int issue_probereq_ex(struct rtw_adapter *padapter,
2777 struct cfg80211_ssid *pssid, u8 *da,
2778 int try_cnt, int wait_ms)
2780 int ret;
2781 int i = 0;
2782 unsigned long start = jiffies;
2784 do {
2785 ret = _issue_probereq(padapter, pssid, da,
2786 wait_ms > 0 ? true : false);
2788 i++;
2790 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2791 break;
2793 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2794 msleep(wait_ms);
2796 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2798 if (ret != _FAIL) {
2799 ret = _SUCCESS;
2800 goto exit;
2803 if (try_cnt && wait_ms) {
2804 if (da)
2805 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
2806 __func__, padapter->pnetdev->name,
2807 da, rtw_get_oper_ch23a(padapter),
2808 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2809 jiffies_to_msecs(jiffies - start));
2810 else
2811 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
2812 __func__, padapter->pnetdev->name,
2813 rtw_get_oper_ch23a(padapter),
2814 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2815 jiffies_to_msecs(jiffies - start));
2817 exit:
2818 return ret;
2821 /* if psta == NULL, indiate we are station(client) now... */
2822 static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
2823 unsigned short status)
2825 struct xmit_frame *pmgntframe;
2826 struct pkt_attrib *pattrib;
2827 unsigned char *pframe;
2828 struct ieee80211_mgmt *mgmt;
2829 unsigned int val32;
2830 u16 auth_algo;
2831 int use_shared_key = 0;
2832 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2833 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2834 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2836 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2837 if (!pmgntframe)
2838 return;
2840 /* update attribute */
2841 pattrib = &pmgntframe->attrib;
2842 update_mgntframe_attrib23a(padapter, pattrib);
2844 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2846 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2847 mgmt = (struct ieee80211_mgmt *)pframe;
2849 mgmt->frame_control =
2850 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
2851 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2852 pmlmeext->mgnt_seq++;
2854 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable);
2856 if (psta) { /* for AP mode */
2857 #ifdef CONFIG_8723AU_AP_MODE
2858 unsigned short val16;
2860 ether_addr_copy(mgmt->da, psta->hwaddr);
2861 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2862 ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv));
2864 /* setting auth algo number */
2865 val16 = (u16)psta->authalg;
2867 if (status != WLAN_STATUS_SUCCESS)
2868 val16 = 0;
2870 if (val16)
2871 use_shared_key = 1;
2873 mgmt->u.auth.auth_alg = cpu_to_le16(val16);
2875 /* setting auth seq number */
2876 mgmt->u.auth.auth_transaction =
2877 cpu_to_le16((u16)psta->auth_seq);
2879 /* setting status code... */
2880 mgmt->u.auth.status_code = cpu_to_le16(status);
2882 pframe = mgmt->u.auth.variable;
2883 /* added challenging text... */
2884 if ((psta->auth_seq == 2) &&
2885 (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
2886 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2887 psta->chg_txt, &pattrib->pktlen);
2888 #endif
2889 } else {
2890 struct ieee80211_mgmt *iv_mgmt;
2892 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
2893 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2894 ether_addr_copy(mgmt->bssid,
2895 get_my_bssid23a(&pmlmeinfo->network));
2897 /* setting auth algo number */
2898 /* 0:OPEN System, 1:Shared key */
2899 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
2900 use_shared_key = 1;
2901 auth_algo = WLAN_AUTH_SHARED_KEY;
2902 } else
2903 auth_algo = WLAN_AUTH_OPEN;
2905 /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
2906 (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
2907 pmlmeinfo->auth_seq); */
2909 /* setting IV for auth seq #3 */
2910 if ((pmlmeinfo->auth_seq == 3) &&
2911 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2912 (use_shared_key == 1)) {
2913 u32 *piv = (u32 *)&mgmt->u.auth;
2915 iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4);
2916 /* DBG_8723A("==> iv(%d), key_index(%d)\n",
2917 pmlmeinfo->iv, pmlmeinfo->key_index); */
2918 val32 = (pmlmeinfo->iv & 0x3fffffff) |
2919 (pmlmeinfo->key_index << 30);
2920 pmlmeinfo->iv++;
2921 put_unaligned_le32(val32, piv);
2923 pattrib->pktlen += 4;
2925 pattrib->iv_len = IEEE80211_WEP_IV_LEN;
2926 } else
2927 iv_mgmt = mgmt;
2929 iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo);
2931 /* setting auth seq number */
2932 iv_mgmt->u.auth.auth_transaction =
2933 cpu_to_le16(pmlmeinfo->auth_seq);
2935 /* setting status code... */
2936 iv_mgmt->u.auth.status_code = cpu_to_le16(status);
2938 pframe = iv_mgmt->u.auth.variable;
2940 /* then checking to see if sending challenging text... */
2941 if ((pmlmeinfo->auth_seq == 3) &&
2942 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2943 (use_shared_key == 1)) {
2944 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2945 pmlmeinfo->chg_txt,
2946 &pattrib->pktlen);
2948 mgmt->frame_control |=
2949 cpu_to_le16(IEEE80211_FCTL_PROTECTED);
2951 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2953 pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40;
2955 pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
2957 pattrib->pktlen += pattrib->icv_len;
2961 pattrib->last_txcmdsz = pattrib->pktlen;
2963 rtw_wep_encrypt23a(padapter, pmgntframe);
2964 DBG_8723A("%s\n", __func__);
2965 dump_mgntframe23a(padapter, pmgntframe);
2967 return;
2970 #ifdef CONFIG_8723AU_AP_MODE
2971 static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
2972 struct sta_info *pstat, u16 pkt_type)
2974 struct xmit_frame *pmgntframe;
2975 struct ieee80211_mgmt *mgmt;
2976 struct pkt_attrib *pattrib;
2977 unsigned char *pframe;
2978 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2979 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2980 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2981 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2982 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
2983 const u8 *p;
2984 u8 *ie = pnetwork->IEs;
2986 DBG_8723A("%s\n", __func__);
2988 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2989 if (!pmgntframe)
2990 return;
2992 /* update attribute */
2993 pattrib = &pmgntframe->attrib;
2994 update_mgntframe_attrib23a(padapter, pattrib);
2996 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2998 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2999 mgmt = (struct ieee80211_mgmt *)pframe;
3001 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
3003 ether_addr_copy(mgmt->da, pstat->hwaddr);
3004 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3005 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3007 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3009 pmlmeext->mgnt_seq++;
3011 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3012 pattrib->pktlen =
3013 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
3015 mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability);
3016 mgmt->u.assoc_resp.status_code = cpu_to_le16(status);
3017 mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
3019 pframe = mgmt->u.assoc_resp.variable;
3021 if (pstat->bssratelen <= 8) {
3022 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3023 pstat->bssratelen, pstat->bssrateset,
3024 &pattrib->pktlen);
3025 } else {
3026 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3027 pstat->bssrateset, &pattrib->pktlen);
3028 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3029 pstat->bssratelen - 8,
3030 pstat->bssrateset + 8, &pattrib->pktlen);
3033 if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
3034 /* FILL HT CAP INFO IE */
3035 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
3036 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie,
3037 pnetwork->IELength);
3038 if (p && p[1]) {
3039 memcpy(pframe, p, p[1] + 2);
3040 pframe += (p[1] + 2);
3041 pattrib->pktlen += (p[1] + 2);
3044 /* FILL HT ADD INFO IE */
3045 /* p = hostapd_eid_ht_operation(hapd, p); */
3046 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie,
3047 pnetwork->IELength);
3048 if (p && p[1] > 0) {
3049 memcpy(pframe, p, p[1] + 2);
3050 pframe += (p[1] + 2);
3051 pattrib->pktlen += (p[1] + 2);
3055 /* FILL WMM IE */
3056 if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) {
3057 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
3058 0x01, 0x01};
3059 int ie_len = 0;
3061 for (p = ie; ; p += (ie_len + 2)) {
3062 p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
3063 pnetwork->IELength - (ie_len + 2));
3064 if (p)
3065 ie_len = p[1];
3066 else
3067 ie_len = 0;
3068 if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) {
3069 memcpy(pframe, p, ie_len + 2);
3070 pframe += (ie_len + 2);
3071 pattrib->pktlen += (ie_len + 2);
3073 break;
3076 if (!p || ie_len == 0)
3077 break;
3081 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
3082 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3083 REALTEK_96B_IE, &pattrib->pktlen);
3086 pattrib->last_txcmdsz = pattrib->pktlen;
3088 dump_mgntframe23a(padapter, pmgntframe);
3090 #endif
3092 static void issue_assocreq(struct rtw_adapter *padapter)
3094 int ret = _FAIL;
3095 struct xmit_frame *pmgntframe;
3096 struct pkt_attrib *pattrib;
3097 unsigned char *pframe;
3098 const u8 *p;
3099 struct ieee80211_mgmt *mgmt;
3100 unsigned int i, j, index = 0;
3101 unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
3102 struct registry_priv *pregpriv = &padapter->registrypriv;
3103 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3104 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3105 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3106 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3107 int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
3108 u8 *pie;
3110 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3111 if (!pmgntframe)
3112 goto exit;
3114 /* update attribute */
3115 pattrib = &pmgntframe->attrib;
3116 update_mgntframe_attrib23a(padapter, pattrib);
3118 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3120 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
3121 mgmt = (struct ieee80211_mgmt *)pframe;
3123 mgmt->frame_control =
3124 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ);
3126 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
3127 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3128 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3130 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3131 pmlmeext->mgnt_seq++;
3133 /* caps */
3134 put_unaligned_le16(pmlmeinfo->network.capability,
3135 &mgmt->u.assoc_req.capab_info);
3136 /* todo: listen interval for power saving */
3137 put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval);
3139 pframe = mgmt->u.assoc_req.variable;
3140 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
3142 /* SSID */
3143 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
3144 pmlmeinfo->network.Ssid.ssid_len,
3145 pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
3147 /* supported rate & extended supported rate */
3149 get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
3150 /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */
3152 /* for JAPAN, channel 14 can only uses B Mode(CCK) */
3153 if (pmlmeext->cur_channel == 14)
3154 sta_bssrate_len = 4;
3156 /* for (i = 0; i < sta_bssrate_len; i++) { */
3157 /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
3158 /* */
3160 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3161 if (pmlmeinfo->network.SupportedRates[i] == 0)
3162 break;
3163 DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
3164 pmlmeinfo->network.SupportedRates[i]);
3167 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3168 if (pmlmeinfo->network.SupportedRates[i] == 0)
3169 break;
3171 /* Check if the AP's supported rates are also
3172 supported by STA. */
3173 for (j = 0; j < sta_bssrate_len; j++) {
3174 /* Avoid the proprietary data rate (22Mbps) of
3175 Handlink WSG-4000 AP */
3176 if ((pmlmeinfo->network.SupportedRates[i] |
3177 IEEE80211_BASIC_RATE_MASK) ==
3178 (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
3179 /* DBG_8723A("match i = %d, j =%d\n", i, j); */
3180 break;
3184 if (j == sta_bssrate_len) {
3185 /* the rate is not supported by STA */
3186 DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
3187 "STA!\n", __func__, i,
3188 pmlmeinfo->network.SupportedRates[i]);
3189 } else {
3190 /* the rate is supported by STA */
3191 bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
3195 bssrate_len = index;
3196 DBG_8723A("bssrate_len = %d\n", bssrate_len);
3198 if (bssrate_len == 0) {
3199 rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
3200 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
3201 goto exit; /* don't connect to AP if no joint supported rate */
3204 if (bssrate_len > 8) {
3205 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3206 bssrate, &pattrib->pktlen);
3207 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3208 (bssrate_len - 8), (bssrate + 8),
3209 &pattrib->pktlen);
3210 } else
3211 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3212 bssrate_len, bssrate, &pattrib->pktlen);
3214 /* RSN */
3216 pie = pmlmeinfo->network.IEs;
3217 pie_len = pmlmeinfo->network.IELength;
3219 p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
3220 if (p)
3221 pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
3222 &pattrib->pktlen);
3224 /* HT caps */
3225 if (padapter->mlmepriv.htpriv.ht_option) {
3226 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
3228 if (p && !is_ap_in_tkip23a(padapter)) {
3229 struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap;
3231 memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap));
3233 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
3234 if (pregpriv->cbw40_enable == 0) {
3235 cap->cap_info &= ~cpu_to_le16(
3236 IEEE80211_HT_CAP_SGI_40 |
3237 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3238 } else {
3239 cap->cap_info |= cpu_to_le16(
3240 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3243 /* todo: disable SM power save mode */
3244 cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
3246 rf_type = rtl8723a_get_rf_type(padapter);
3247 /* switch (pregpriv->rf_config) */
3248 switch (rf_type) {
3249 case RF_1T1R:
3250 /* RX STBC One spatial stream */
3251 if (pregpriv->rx_stbc)
3252 cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3254 memcpy(&cap->mcs, MCS_rate_1R23A, 16);
3255 break;
3257 case RF_2T2R:
3258 case RF_1T2R:
3259 default:
3260 /* enable for 2.4/5 GHz */
3261 if (pregpriv->rx_stbc == 0x3 ||
3262 (pmlmeext->cur_wireless_mode &
3263 WIRELESS_11_24N &&
3264 /* enable for 2.4GHz */
3265 pregpriv->rx_stbc == 0x1) ||
3266 (pmlmeext->cur_wireless_mode &
3267 WIRELESS_11_5N &&
3268 pregpriv->rx_stbc == 0x2) ||
3269 /* enable for 5GHz */
3270 pregpriv->wifi_spec == 1) {
3271 DBG_8723A("declare supporting RX "
3272 "STBC\n");
3273 /* RX STBC two spatial stream */
3274 cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3276 memcpy(&cap->mcs, MCS_rate_2R23A, 16);
3277 break;
3280 if (rtl8723a_BT_coexist(padapter) &&
3281 rtl8723a_BT_using_antenna_1(padapter)) {
3282 /* set to 8K */
3283 cap->ampdu_params_info &=
3284 ~IEEE80211_HT_AMPDU_PARM_FACTOR;
3285 /* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */
3288 pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
3289 p[1], (u8 *)&pmlmeinfo->ht_cap,
3290 &pattrib->pktlen);
3294 /* vendor specific IE, such as WPA, WMM, WPS */
3295 for (i = 0; i < pmlmeinfo->network.IELength;) {
3296 p = pmlmeinfo->network.IEs + i;
3298 switch (p[0]) {
3299 case WLAN_EID_VENDOR_SPECIFIC:
3300 if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) ||
3301 !memcmp(p + 2, WMM_OUI23A, 4) ||
3302 !memcmp(p + 2, WPS_OUI23A, 4)) {
3303 u8 plen = p[1];
3305 if (!padapter->registrypriv.wifi_spec) {
3306 /* Commented by Kurt 20110629 */
3307 /* In some older APs, WPS handshake */
3308 /* would be fail if we append vender
3309 extensions informations to AP */
3310 if (!memcmp(p + 2, WPS_OUI23A, 4))
3311 plen = 14;
3313 pframe = rtw_set_ie23a(pframe,
3314 WLAN_EID_VENDOR_SPECIFIC,
3315 plen, p + 2,
3316 &pattrib->pktlen);
3318 break;
3320 default:
3321 break;
3324 i += p[1] + 2;
3327 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3328 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3329 REALTEK_96B_IE, &pattrib->pktlen);
3331 pattrib->last_txcmdsz = pattrib->pktlen;
3332 dump_mgntframe23a(padapter, pmgntframe);
3334 ret = _SUCCESS;
3336 exit:
3337 pmlmepriv->assoc_req_len = 0;
3338 if (ret == _SUCCESS) {
3339 kfree(pmlmepriv->assoc_req);
3340 pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
3341 if (pmlmepriv->assoc_req) {
3342 memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen);
3343 pmlmepriv->assoc_req_len = pattrib->pktlen;
3345 } else
3346 kfree(pmlmepriv->assoc_req);
3348 return;
3351 /* when wait_ack is true, this function should be called at process context */
3352 static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3353 unsigned int power_mode, int wait_ack)
3355 int ret = _FAIL;
3356 struct xmit_frame *pmgntframe;
3357 struct pkt_attrib *pattrib;
3358 unsigned char *pframe;
3359 struct ieee80211_hdr *pwlanhdr;
3360 struct xmit_priv *pxmitpriv;
3361 struct mlme_ext_priv *pmlmeext;
3362 struct mlme_ext_info *pmlmeinfo;
3364 /* DBG_8723A("%s:%d\n", __func__, power_mode); */
3366 if (!padapter)
3367 goto exit;
3369 pxmitpriv = &padapter->xmitpriv;
3370 pmlmeext = &padapter->mlmeextpriv;
3371 pmlmeinfo = &pmlmeext->mlmext_info;
3373 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3374 if (!pmgntframe)
3375 goto exit;
3377 /* update attribute */
3378 pattrib = &pmgntframe->attrib;
3379 update_mgntframe_attrib23a(padapter, pattrib);
3380 pattrib->retry_ctrl = false;
3382 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3384 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3385 pwlanhdr = (struct ieee80211_hdr *)pframe;
3387 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3388 IEEE80211_STYPE_NULLFUNC);
3390 if ((pmlmeinfo->state&0x03) == MSR_AP)
3391 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3392 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3393 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3395 if (power_mode)
3396 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
3398 ether_addr_copy(pwlanhdr->addr1, da);
3399 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3400 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3402 pwlanhdr->seq_ctrl =
3403 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3404 pmlmeext->mgnt_seq++;
3406 pframe += sizeof(struct ieee80211_hdr_3addr);
3407 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3409 pattrib->last_txcmdsz = pattrib->pktlen;
3411 if (wait_ack)
3412 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3413 else {
3414 dump_mgntframe23a(padapter, pmgntframe);
3415 ret = _SUCCESS;
3418 exit:
3419 return ret;
3422 /* when wait_ms >0 , this function should be called at process context */
3423 /* da == NULL for station mode */
3424 int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3425 unsigned int power_mode, int try_cnt, int wait_ms)
3427 int ret;
3428 int i = 0;
3429 unsigned long start = jiffies;
3430 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3431 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3433 /* da == NULL, assume it's null data for sta to ap*/
3434 if (da == NULL)
3435 da = get_my_bssid23a(&pmlmeinfo->network);
3437 do {
3438 ret = _issue_nulldata23a(padapter, da, power_mode,
3439 wait_ms > 0 ? true : false);
3441 i++;
3443 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3444 break;
3446 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3447 msleep(wait_ms);
3449 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3451 if (ret != _FAIL) {
3452 ret = _SUCCESS;
3453 goto exit;
3456 if (try_cnt && wait_ms) {
3457 if (da)
3458 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3459 __func__, padapter->pnetdev->name,
3460 da, rtw_get_oper_ch23a(padapter),
3461 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3462 jiffies_to_msecs(jiffies - start));
3463 else
3464 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3465 __func__, padapter->pnetdev->name,
3466 rtw_get_oper_ch23a(padapter),
3467 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3468 jiffies_to_msecs(jiffies - start));
3470 exit:
3471 return ret;
3474 /* when wait_ack is true, this function should be called at process context */
3475 static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
3476 unsigned char *da, u16 tid, int wait_ack)
3478 int ret = _FAIL;
3479 struct xmit_frame *pmgntframe;
3480 struct pkt_attrib *pattrib;
3481 unsigned char *pframe;
3482 struct ieee80211_qos_hdr *pwlanhdr;
3483 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3484 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3485 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3487 DBG_8723A("%s\n", __func__);
3489 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3490 if (!pmgntframe)
3491 goto exit;
3493 /* update attribute */
3494 pattrib = &pmgntframe->attrib;
3495 update_mgntframe_attrib23a(padapter, pattrib);
3497 pattrib->hdrlen += 2;
3498 pattrib->qos_en = true;
3499 pattrib->eosp = 1;
3500 pattrib->ack_policy = 0;
3501 pattrib->mdata = 0;
3503 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3505 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3506 pwlanhdr = (struct ieee80211_qos_hdr *)pframe;
3508 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3509 IEEE80211_STYPE_QOS_NULLFUNC);
3511 if ((pmlmeinfo->state&0x03) == MSR_AP)
3512 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3513 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3514 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3516 if (pattrib->mdata)
3517 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
3519 pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK);
3520 pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) &
3521 IEEE80211_QOS_CTL_ACK_POLICY_MASK);
3522 if (pattrib->eosp)
3523 pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
3525 ether_addr_copy(pwlanhdr->addr1, da);
3526 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3527 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3529 pwlanhdr->seq_ctrl =
3530 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3531 pmlmeext->mgnt_seq++;
3533 pframe += sizeof(struct ieee80211_qos_hdr);
3534 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3536 pattrib->last_txcmdsz = pattrib->pktlen;
3538 if (wait_ack)
3539 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3540 else {
3541 dump_mgntframe23a(padapter, pmgntframe);
3542 ret = _SUCCESS;
3545 exit:
3546 return ret;
3549 /* when wait_ms >0 , this function should be called at process context */
3550 /* da == NULL for station mode */
3551 int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3552 u16 tid, int try_cnt, int wait_ms)
3554 int ret;
3555 int i = 0;
3556 unsigned long start = jiffies;
3557 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3558 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3560 /* da == NULL, assume it's null data for sta to ap*/
3561 if (da == NULL)
3562 da = get_my_bssid23a(&pmlmeinfo->network);
3564 do {
3565 ret = _issue_qos_nulldata23a(padapter, da, tid,
3566 wait_ms > 0 ? true : false);
3568 i++;
3570 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3571 break;
3573 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3574 msleep(wait_ms);
3575 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3577 if (ret != _FAIL) {
3578 ret = _SUCCESS;
3579 goto exit;
3582 if (try_cnt && wait_ms) {
3583 if (da)
3584 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3585 __func__, padapter->pnetdev->name,
3586 da, rtw_get_oper_ch23a(padapter),
3587 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3588 jiffies_to_msecs(jiffies - start));
3589 else
3590 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3591 __func__, padapter->pnetdev->name,
3592 rtw_get_oper_ch23a(padapter),
3593 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3594 jiffies_to_msecs(jiffies - start));
3596 exit:
3597 return ret;
3600 static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da,
3601 unsigned short reason, u8 wait_ack)
3603 struct xmit_frame *pmgntframe;
3604 struct pkt_attrib *pattrib;
3605 struct ieee80211_mgmt *mgmt;
3606 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3607 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3608 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3609 int ret = _FAIL;
3611 /* DBG_8723A("%s to %pM\n", __func__, da); */
3613 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3614 if (!pmgntframe)
3615 goto exit;
3617 /* update attribute */
3618 pattrib = &pmgntframe->attrib;
3619 update_mgntframe_attrib23a(padapter, pattrib);
3620 pattrib->retry_ctrl = false;
3622 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3624 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3626 mgmt->frame_control =
3627 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
3629 ether_addr_copy(mgmt->da, da);
3630 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3631 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3633 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3634 pmlmeext->mgnt_seq++;
3636 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2;
3638 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
3640 pattrib->last_txcmdsz = pattrib->pktlen;
3642 if (wait_ack)
3643 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3644 else {
3645 dump_mgntframe23a(padapter, pmgntframe);
3646 ret = _SUCCESS;
3649 exit:
3650 return ret;
3653 int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
3654 unsigned short reason)
3656 DBG_8723A("%s to %pM\n", __func__, da);
3657 return _issue_deauth(padapter, da, reason, false);
3660 static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
3661 unsigned short reason, int try_cnt, int wait_ms)
3663 int ret;
3664 int i = 0;
3665 unsigned long start = jiffies;
3667 do {
3668 ret = _issue_deauth(padapter, da, reason,
3669 wait_ms >0 ? true : false);
3671 i++;
3673 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3674 break;
3676 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3677 msleep(wait_ms);
3679 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3681 if (ret != _FAIL) {
3682 ret = _SUCCESS;
3683 goto exit;
3686 if (try_cnt && wait_ms) {
3687 if (da)
3688 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3689 __func__, padapter->pnetdev->name,
3690 da, rtw_get_oper_ch23a(padapter),
3691 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3692 jiffies_to_msecs(jiffies - start));
3693 else
3694 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3695 __func__, padapter->pnetdev->name,
3696 rtw_get_oper_ch23a(padapter),
3697 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3698 jiffies_to_msecs(jiffies - start));
3700 exit:
3701 return ret;
3704 void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
3705 u8 *ra, u8 new_ch, u8 ch_offset)
3707 struct xmit_frame *pmgntframe;
3708 struct pkt_attrib *pattrib;
3709 unsigned char *pframe;
3710 struct ieee80211_mgmt *mgmt;
3711 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3712 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3714 DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n",
3715 __func__, padapter->pnetdev->name, ra, new_ch, ch_offset);
3717 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3718 if (!pmgntframe)
3719 return;
3721 /* update attribute */
3722 pattrib = &pmgntframe->attrib;
3723 update_mgntframe_attrib23a(padapter, pattrib);
3725 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3727 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3729 mgmt->frame_control =
3730 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3732 ether_addr_copy(mgmt->da, ra); /* RA */
3733 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */
3734 ether_addr_copy(mgmt->bssid, ra); /* DA = RA */
3736 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3737 pmlmeext->mgnt_seq++;
3739 mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
3740 mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
3742 pframe = mgmt->u.action.u.chan_switch.variable;
3743 pattrib->pktlen = offsetof(struct ieee80211_mgmt,
3744 u.action.u.chan_switch.variable);
3746 pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
3747 new_ch, 0);
3748 pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
3749 hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
3751 pattrib->last_txcmdsz = pattrib->pktlen;
3753 dump_mgntframe23a(padapter, pmgntframe);
3756 void issue_action_BA23a(struct rtw_adapter *padapter,
3757 const unsigned char *raddr,
3758 unsigned char action, unsigned short status)
3760 u16 start_seq;
3761 u16 BA_para_set;
3762 u16 BA_starting_seqctrl;
3763 u16 BA_para;
3764 int max_rx_ampdu_factor;
3765 struct xmit_frame *pmgntframe;
3766 struct pkt_attrib *pattrib;
3767 struct ieee80211_mgmt *mgmt;
3768 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3769 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3770 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3771 struct sta_info *psta;
3772 struct sta_priv *pstapriv = &padapter->stapriv;
3773 struct registry_priv *pregpriv = &padapter->registrypriv;
3774 u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
3776 DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status);
3778 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3779 if (!pmgntframe)
3780 return;
3782 /* update attribute */
3783 pattrib = &pmgntframe->attrib;
3784 update_mgntframe_attrib23a(padapter, pattrib);
3786 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3788 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3790 mgmt->frame_control =
3791 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3793 ether_addr_copy(mgmt->da, raddr);
3794 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3795 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3797 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3798 pmlmeext->mgnt_seq++;
3800 mgmt->u.action.category = WLAN_CATEGORY_BACK;
3802 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1;
3804 switch (action) {
3805 case WLAN_ACTION_ADDBA_REQ:
3806 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req);
3808 mgmt->u.action.u.addba_req.action_code = action;
3810 do {
3811 pmlmeinfo->dialogToken++;
3812 } while (pmlmeinfo->dialogToken == 0);
3814 mgmt->u.action.u.addba_req.dialog_token =
3815 pmlmeinfo->dialogToken;
3817 if (rtl8723a_BT_coexist(padapter) &&
3818 rtl8723a_BT_using_antenna_1(padapter) &&
3819 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3820 memcmp(raddr, tendaAPMac, 3))) {
3821 /* A-MSDU NOT Supported */
3822 BA_para_set = 0;
3823 /* immediate Block Ack */
3824 BA_para_set |= (1 << 1) &
3825 IEEE80211_ADDBA_PARAM_POLICY_MASK;
3826 /* TID */
3827 BA_para_set |= (status << 2) &
3828 IEEE80211_ADDBA_PARAM_TID_MASK;
3829 /* max buffer size is 8 MSDU */
3830 BA_para_set |= (8 << 6) &
3831 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3832 } else {
3833 /* immediate ack & 64 buffer size */
3834 BA_para_set = 0x1002 | ((status & 0xf) << 2);
3837 put_unaligned_le16(BA_para_set,
3838 &mgmt->u.action.u.addba_req.capab);
3840 /* 5ms */
3841 put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout);
3843 psta = rtw_get_stainfo23a(pstapriv, raddr);
3844 if (psta) {
3845 int idx;
3847 idx = status & 0x07;
3848 start_seq =
3849 (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1;
3851 DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
3852 start_seq, idx);
3854 psta->BA_starting_seqctrl[idx] = start_seq;
3856 BA_starting_seqctrl = start_seq << 4;
3857 } else
3858 BA_starting_seqctrl = 0;
3860 put_unaligned_le16(BA_starting_seqctrl,
3861 &mgmt->u.action.u.addba_req.start_seq_num);
3863 break;
3865 case WLAN_ACTION_ADDBA_RESP:
3866 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp);
3868 mgmt->u.action.u.addba_resp.action_code = action;
3869 mgmt->u.action.u.addba_resp.dialog_token =
3870 pmlmeinfo->ADDBA_req.dialog_token;
3871 put_unaligned_le16(status,
3872 &mgmt->u.action.u.addba_resp.status);
3874 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
3875 &max_rx_ampdu_factor);
3877 BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
3878 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
3879 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
3880 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
3881 BA_para_set = BA_para | 0x0800; /* 32 buffer size */
3882 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
3883 BA_para_set = BA_para | 0x0400; /* 16 buffer size */
3884 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
3885 BA_para_set = BA_para | 0x0200; /* 8 buffer size */
3886 else
3887 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
3889 if (rtl8723a_BT_coexist(padapter) &&
3890 rtl8723a_BT_using_antenna_1(padapter) &&
3891 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3892 memcmp(raddr, tendaAPMac, 3))) {
3893 /* max buffer size is 8 MSDU */
3894 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3895 BA_para_set |= (8 << 6) &
3896 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3899 if (pregpriv->ampdu_amsdu == 0)/* disabled */
3900 BA_para_set &= ~BIT(0);
3901 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
3902 BA_para_set |= BIT(0);
3904 put_unaligned_le16(BA_para_set,
3905 &mgmt->u.action.u.addba_resp.capab);
3907 mgmt->u.action.u.addba_resp.timeout
3908 = pmlmeinfo->ADDBA_req.BA_timeout_value;
3910 pattrib->pktlen += 8;
3911 break;
3912 case WLAN_ACTION_DELBA:
3913 pattrib->pktlen += sizeof(mgmt->u.action.u.delba);
3915 mgmt->u.action.u.delba.action_code = action;
3916 BA_para_set = (status & 0x1F) << 3;
3917 mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set);
3918 mgmt->u.action.u.delba.reason_code =
3919 cpu_to_le16(WLAN_REASON_QSTA_NOT_USE);
3921 pattrib->pktlen += 5;
3922 break;
3923 default:
3924 break;
3927 pattrib->last_txcmdsz = pattrib->pktlen;
3929 dump_mgntframe23a(padapter, pmgntframe);
3932 int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
3934 struct sta_priv *pstapriv = &padapter->stapriv;
3935 struct sta_info *psta = NULL;
3936 /* struct recv_reorder_ctrl *preorder_ctrl; */
3937 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3938 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3939 u16 tid;
3941 if ((pmlmeinfo->state&0x03) != MSR_AP)
3942 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3943 return _SUCCESS;
3945 psta = rtw_get_stainfo23a(pstapriv, addr);
3946 if (psta == NULL)
3947 return _SUCCESS;
3949 if (initiator == 0) { /* recipient */
3950 for (tid = 0; tid < MAXTID; tid++) {
3951 if (psta->recvreorder_ctrl[tid].enable == true) {
3952 DBG_8723A("rx agg disable tid(%d)\n", tid);
3953 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3954 psta->recvreorder_ctrl[tid].enable = false;
3955 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
3958 } else if (initiator == 1) { /* originator */
3959 for (tid = 0; tid < MAXTID; tid++) {
3960 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
3961 DBG_8723A("tx agg disable tid(%d)\n", tid);
3962 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3963 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3964 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3969 return _SUCCESS;
3972 int send_beacon23a(struct rtw_adapter *padapter)
3974 bool bxmitok;
3975 int issue = 0;
3976 int poll = 0;
3977 unsigned long start = jiffies;
3978 unsigned int passing_time;
3980 rtl8723a_bcn_valid(padapter);
3981 do {
3982 issue_beacon23a(padapter, 100);
3983 issue++;
3984 do {
3985 yield();
3986 bxmitok = rtl8723a_get_bcn_valid(padapter);
3987 poll++;
3988 } while ((poll % 10) != 0 && !bxmitok &&
3989 !padapter->bSurpriseRemoved &&
3990 !padapter->bDriverStopped);
3992 } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
3993 !padapter->bDriverStopped);
3995 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
3996 return _FAIL;
3998 passing_time = jiffies_to_msecs(jiffies - start);
4000 if (!bxmitok) {
4001 DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
4002 return _FAIL;
4003 } else {
4005 if (passing_time > 100 || issue > 3)
4006 DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
4007 __func__, issue, poll, passing_time);
4008 return _SUCCESS;
4012 /****************************************************************************
4014 Following are some utitity functions for WiFi MLME
4016 *****************************************************************************/
4018 bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
4021 int i = 0;
4022 u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
4023 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
4024 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
4025 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
4026 161, 163, 165};
4027 for (i = 0; i < sizeof(Channel_5G); i++)
4028 if (channel == Channel_5G[i])
4029 return true;
4030 return false;
4033 static void rtw_site_survey(struct rtw_adapter *padapter)
4035 unsigned char survey_channel = 0;
4036 enum rt_scan_type ScanType = SCAN_PASSIVE;
4037 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4038 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4039 struct rtw_ieee80211_channel *ch;
4041 if (pmlmeext->sitesurvey_res.channel_idx <
4042 pmlmeext->sitesurvey_res.ch_num) {
4043 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
4044 survey_channel = ch->hw_value;
4045 ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ?
4046 SCAN_PASSIVE : SCAN_ACTIVE;
4049 if (survey_channel != 0) {
4050 /* PAUSE 4-AC Queue when site_survey */
4051 if (pmlmeext->sitesurvey_res.channel_idx == 0)
4052 set_channel_bwmode23a(padapter, survey_channel,
4053 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
4054 HT_CHANNEL_WIDTH_20);
4055 else
4056 SelectChannel23a(padapter, survey_channel);
4058 if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
4060 int i;
4062 for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
4063 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
4064 /* todo: to issue two probe req??? */
4065 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4066 /* msleep(SURVEY_TO>>1); */
4067 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4071 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4072 /* todo: to issue two probe req??? */
4073 issue_probereq(padapter, NULL, NULL);
4074 /* msleep(SURVEY_TO>>1); */
4075 issue_probereq(padapter, NULL, NULL);
4079 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
4080 } else {
4081 /* channel number is 0 or this channel is not valid. */
4082 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
4084 /* switch back to the original channel */
4086 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
4087 pmlmeext->cur_ch_offset,
4088 pmlmeext->cur_bwmode);
4090 /* flush 4-AC Queue after rtw_site_survey */
4091 /* val8 = 0; */
4093 /* config MSR */
4094 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4096 /* restore RX GAIN */
4097 rtl8723a_set_initial_gain(padapter, 0xff);
4098 /* turn on dynamic functions */
4099 rtl8723a_odm_support_ability_restore(padapter);
4101 if (is_client_associated_to_ap23a(padapter) == true)
4102 issue_nulldata23a(padapter, NULL, 0, 3, 500);
4104 rtl8723a_mlme_sitesurvey(padapter, 0);
4106 report_surveydone_event23a(padapter);
4108 pmlmeext->chan_scan_time = SURVEY_TO;
4109 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
4112 return;
4115 /* collect bss info from Beacon and Probe request/response frames. */
4116 static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
4117 struct recv_frame *precv_frame)
4119 struct sk_buff *skb = precv_frame->pkt;
4120 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
4121 struct registry_priv *pregistrypriv = &padapter->registrypriv;
4122 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4123 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4124 struct wlan_bssid_ex *bssid;
4125 const u8 *p;
4126 u8 *pie;
4127 unsigned int length;
4128 int i;
4130 length = skb->len;
4132 bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
4133 if (!bssid)
4134 return NULL;
4136 if (ieee80211_is_beacon(mgmt->frame_control)) {
4137 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4138 pie = mgmt->u.beacon.variable;
4139 bssid->reserved = 1;
4140 bssid->capability =
4141 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4142 bssid->beacon_interval =
4143 get_unaligned_le16(&mgmt->u.beacon.beacon_int);
4144 bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
4145 } else if (ieee80211_is_probe_req(mgmt->frame_control)) {
4146 length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
4147 pie = mgmt->u.probe_req.variable;
4148 bssid->reserved = 2;
4149 bssid->capability = 0;
4150 bssid->beacon_interval =
4151 padapter->registrypriv.dev_network.beacon_interval;
4152 bssid->tsf = 0;
4153 } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
4154 length -=
4155 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
4156 pie = mgmt->u.probe_resp.variable;
4157 bssid->reserved = 3;
4158 bssid->capability =
4159 get_unaligned_le16(&mgmt->u.probe_resp.capab_info);
4160 bssid->beacon_interval =
4161 get_unaligned_le16(&mgmt->u.probe_resp.beacon_int);
4162 bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp);
4163 } else {
4164 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4165 pie = mgmt->u.beacon.variable;
4166 bssid->reserved = 0;
4167 bssid->capability =
4168 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4169 bssid->beacon_interval =
4170 padapter->registrypriv.dev_network.beacon_interval;
4171 bssid->tsf = 0;
4174 if (length > MAX_IE_SZ) {
4175 /* DBG_8723A("IE too long for survey event\n"); */
4176 kfree(bssid);
4177 return NULL;
4180 bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
4182 /* below is to copy the information element */
4183 bssid->IELength = length;
4184 memcpy(bssid->IEs, pie, bssid->IELength);
4186 /* get the signal strength */
4187 /* in dBM.raw data */
4188 bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
4189 bssid->SignalQuality =
4190 precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
4191 bssid->SignalStrength =
4192 precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
4194 /* checking SSID */
4195 p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength);
4197 if (!p) {
4198 DBG_8723A("marc: cannot find SSID for survey event\n");
4199 goto fail;
4202 if (p[1] > IEEE80211_MAX_SSID_LEN) {
4203 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4204 "event\n", __func__, __LINE__, p[1]);
4205 goto fail;
4207 memcpy(bssid->Ssid.ssid, p + 2, p[1]);
4208 bssid->Ssid.ssid_len = p[1];
4210 /* checking rate info... */
4211 i = 0;
4212 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength);
4213 if (p) {
4214 if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
4215 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4216 "event\n", __func__, __LINE__, p[1]);
4217 goto fail;
4219 memcpy(bssid->SupportedRates, p + 2, p[1]);
4220 i = p[1];
4223 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs,
4224 bssid->IELength);
4225 if (p) {
4226 if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
4227 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4228 "event\n", __func__, __LINE__, p[1]);
4229 goto fail;
4231 memcpy(bssid->SupportedRates + i, p + 2, p[1]);
4234 /* Checking for DSConfig */
4235 p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength);
4237 bssid->DSConfig = 0;
4239 if (p) {
4240 bssid->DSConfig = p[2];
4241 } else {/* In 5G, some ap do not have DSSET IE */
4242 /* checking HT info for channel */
4243 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs,
4244 bssid->IELength);
4245 if (p) {
4246 struct ieee80211_ht_operation *HT_info =
4247 (struct ieee80211_ht_operation *)(p + 2);
4248 bssid->DSConfig = HT_info->primary_chan;
4249 } else /* use current channel */
4250 bssid->DSConfig = rtw_get_oper_ch23a(padapter);
4253 if (ieee80211_is_probe_req(mgmt->frame_control)) {
4254 /* FIXME */
4255 bssid->ifmode = NL80211_IFTYPE_STATION;
4256 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4257 bssid->Privacy = 1;
4258 return bssid;
4261 if (bssid->capability & WLAN_CAPABILITY_ESS) {
4262 bssid->ifmode = NL80211_IFTYPE_STATION;
4263 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4264 } else {
4265 bssid->ifmode = NL80211_IFTYPE_ADHOC;
4266 ether_addr_copy(bssid->MacAddress, mgmt->bssid);
4269 if (bssid->capability & WLAN_CAPABILITY_PRIVACY)
4270 bssid->Privacy = 1;
4271 else
4272 bssid->Privacy = 0;
4274 bssid->ATIMWindow = 0;
4276 /* 20/40 BSS Coexistence check */
4277 if (pregistrypriv->wifi_spec == 1 &&
4278 pmlmeinfo->bwmode_updated == false) {
4279 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4281 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs,
4282 bssid->IELength);
4283 if (p && p[1] > 0) {
4284 struct ieee80211_ht_cap *pHT_caps;
4286 pHT_caps = (struct ieee80211_ht_cap *)(p + 2);
4288 if (pHT_caps->cap_info &
4289 cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT))
4290 pmlmepriv->num_FortyMHzIntolerant++;
4291 } else
4292 pmlmepriv->num_sta_no_ht++;
4296 /* mark bss info receiving from nearby channel as SignalQuality 101 */
4297 if (bssid->DSConfig != rtw_get_oper_ch23a(padapter))
4298 bssid->SignalQuality = 101;
4300 return bssid;
4301 fail:
4302 kfree (bssid);
4303 return NULL;
4306 static void start_create_ibss(struct rtw_adapter *padapter)
4308 unsigned short caps;
4309 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4310 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4311 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4313 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4314 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4316 /* update wireless mode */
4317 update_wireless_mode23a(padapter);
4319 /* update capability */
4320 caps = pnetwork->capability;
4321 update_capinfo23a(padapter, caps);
4322 if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */
4323 rtl8723a_set_sec_cfg(padapter, 0xcf);
4325 /* switch channel */
4326 /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4327 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
4329 rtl8723a_SetBeaconRelatedRegisters(padapter);
4331 /* set msr to MSR_ADHOC */
4332 pmlmeinfo->state = MSR_ADHOC;
4333 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4335 /* issue beacon */
4336 if (send_beacon23a(padapter) == _FAIL) {
4337 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
4338 "issuing beacon frame fail....\n");
4340 report_join_res23a(padapter, -1);
4341 pmlmeinfo->state = MSR_NOLINK;
4342 } else {
4343 hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
4344 hw_var_set_mlme_join(padapter, 0);
4346 report_join_res23a(padapter, 1);
4347 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4349 } else {
4350 DBG_8723A("%s: invalid cap:%x\n", __func__, caps);
4351 return;
4355 static void start_clnt_join(struct rtw_adapter *padapter)
4357 unsigned short caps;
4358 u8 val8;
4359 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4360 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4361 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4362 int beacon_timeout;
4364 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4365 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4367 /* update wireless mode */
4368 update_wireless_mode23a(padapter);
4370 /* update capability */
4371 caps = pnetwork->capability;
4372 update_capinfo23a(padapter, caps);
4373 if (caps & WLAN_CAPABILITY_ESS) {
4374 /* switch channel */
4375 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4377 rtl8723a_set_media_status(padapter, MSR_INFRA);
4379 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
4380 0xcc: 0xcf;
4382 rtl8723a_set_sec_cfg(padapter, val8);
4384 /* switch channel */
4385 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
4387 /* here wait for receiving the beacon to start auth */
4388 /* and enable a timer */
4389 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
4390 set_link_timer(pmlmeext, beacon_timeout);
4391 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
4392 msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
4393 pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA;
4394 } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */
4395 rtl8723a_set_media_status(padapter, MSR_ADHOC);
4397 rtl8723a_set_sec_cfg(padapter, 0xcf);
4399 /* switch channel */
4400 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4402 rtl8723a_SetBeaconRelatedRegisters(padapter);
4404 pmlmeinfo->state = MSR_ADHOC;
4406 report_join_res23a(padapter, 1);
4407 } else {
4408 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
4409 return;
4413 static void start_clnt_auth(struct rtw_adapter *padapter)
4415 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4416 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4418 del_timer_sync(&pmlmeext->link_timer);
4420 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4421 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4423 pmlmeinfo->auth_seq = 1;
4424 pmlmeinfo->reauth_count = 0;
4425 pmlmeinfo->reassoc_count = 0;
4426 pmlmeinfo->link_count = 0;
4427 pmlmeext->retry = 0;
4429 /* Because of AP's not receiving deauth before */
4430 /* AP may: 1)not response auth or 2)deauth us after link is complete */
4431 /* issue deauth before issuing auth to deal with the situation */
4432 /* Commented by Albert 2012/07/21 */
4433 /* For the Win8 P2P connection, it will be hard to have a
4434 successful connection if this Wi-Fi doesn't connect to it. */
4435 issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress,
4436 WLAN_REASON_DEAUTH_LEAVING);
4438 DBG_8723A_LEVEL(_drv_always_, "start auth\n");
4439 issue_auth(padapter, NULL, 0);
4441 set_link_timer(pmlmeext, REAUTH_TO);
4444 static void start_clnt_assoc(struct rtw_adapter *padapter)
4446 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4447 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4449 del_timer_sync(&pmlmeext->link_timer);
4451 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4452 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4454 issue_assocreq(padapter);
4456 set_link_timer(pmlmeext, REASSOC_TO);
4459 int receive_disconnect23a(struct rtw_adapter *padapter,
4460 unsigned char *MacAddr, unsigned short reason)
4462 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4463 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4465 /* check A3 */
4466 if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
4467 return _SUCCESS;
4469 DBG_8723A("%s\n", __func__);
4471 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
4472 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4473 pmlmeinfo->state = MSR_NOLINK;
4474 report_del_sta_event23a(padapter, MacAddr, reason);
4476 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4477 pmlmeinfo->state = MSR_NOLINK;
4478 report_join_res23a(padapter, -2);
4482 return _SUCCESS;
4485 static void process_80211d(struct rtw_adapter *padapter,
4486 struct wlan_bssid_ex *bssid)
4488 struct registry_priv *pregistrypriv;
4489 struct mlme_ext_priv *pmlmeext;
4490 struct rt_channel_info *chplan_new;
4491 u8 channel;
4492 u8 i;
4494 pregistrypriv = &padapter->registrypriv;
4495 pmlmeext = &padapter->mlmeextpriv;
4497 /* Adjust channel plan by AP Country IE */
4498 if (pregistrypriv->enable80211d &&
4499 !pmlmeext->update_channel_plan_by_ap_done) {
4500 const u8 *ie, *p;
4501 struct rt_channel_plan chplan_ap;
4502 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4503 u8 country[4];
4504 u8 fcn; /* first channel number */
4505 u8 noc; /* number of channel */
4506 u8 j, k;
4508 ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs,
4509 bssid->IELength);
4510 if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
4511 return;
4513 p = ie + 2;
4514 ie += ie[1];
4515 ie += 2;
4517 memcpy(country, p, 3);
4518 country[3] = '\0';
4520 p += 3;
4521 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4522 "%s: 802.11d country =%s\n", __func__, country);
4524 i = 0;
4525 while ((ie - p) >= 3) {
4526 fcn = *(p++);
4527 noc = *(p++);
4528 p++;
4530 for (j = 0; j < noc; j++) {
4531 if (fcn <= 14)
4532 channel = fcn + j; /* 2.4 GHz */
4533 else
4534 channel = fcn + j * 4; /* 5 GHz */
4536 chplan_ap.Channel[i++] = channel;
4539 chplan_ap.Len = i;
4541 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4542 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4543 chplan_new = pmlmeext->channel_set;
4545 i = j = k = 0;
4546 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4547 do {
4548 if (i == MAX_CHANNEL_NUM ||
4549 chplan_sta[i].ChannelNum == 0 ||
4550 chplan_sta[i].ChannelNum > 14)
4551 break;
4553 if (j == chplan_ap.Len ||
4554 chplan_ap.Channel[j] > 14)
4555 break;
4557 if (chplan_sta[i].ChannelNum ==
4558 chplan_ap.Channel[j]) {
4559 chplan_new[k].ChannelNum =
4560 chplan_ap.Channel[j];
4561 chplan_new[k].ScanType = SCAN_ACTIVE;
4562 i++;
4563 j++;
4564 k++;
4565 } else if (chplan_sta[i].ChannelNum <
4566 chplan_ap.Channel[j]) {
4567 chplan_new[k].ChannelNum =
4568 chplan_sta[i].ChannelNum;
4569 chplan_new[k].ScanType =
4570 SCAN_PASSIVE;
4571 i++;
4572 k++;
4573 } else if (chplan_sta[i].ChannelNum >
4574 chplan_ap.Channel[j]) {
4575 chplan_new[k].ChannelNum =
4576 chplan_ap.Channel[j];
4577 chplan_new[k].ScanType =
4578 SCAN_ACTIVE;
4579 j++;
4580 k++;
4582 } while (1);
4584 /* change AP not support channel to Passive scan */
4585 while (i < MAX_CHANNEL_NUM &&
4586 chplan_sta[i].ChannelNum != 0 &&
4587 chplan_sta[i].ChannelNum <= 14) {
4588 chplan_new[k].ChannelNum =
4589 chplan_sta[i].ChannelNum;
4590 chplan_new[k].ScanType = SCAN_PASSIVE;
4591 i++;
4592 k++;
4595 /* add channel AP supported */
4596 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
4597 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4598 chplan_new[k].ScanType = SCAN_ACTIVE;
4599 j++;
4600 k++;
4602 } else {
4603 /* keep original STA 2.4G channel plan */
4604 while (i < MAX_CHANNEL_NUM &&
4605 chplan_sta[i].ChannelNum != 0 &&
4606 chplan_sta[i].ChannelNum <= 14) {
4607 chplan_new[k].ChannelNum =
4608 chplan_sta[i].ChannelNum;
4609 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4610 i++;
4611 k++;
4614 /* skip AP 2.4G channel plan */
4615 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
4616 j++;
4619 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4620 do {
4621 if (i == MAX_CHANNEL_NUM ||
4622 chplan_sta[i].ChannelNum == 0)
4623 break;
4625 if (j == chplan_ap.Len ||
4626 chplan_ap.Channel[j] == 0)
4627 break;
4629 if (chplan_sta[i].ChannelNum ==
4630 chplan_ap.Channel[j]) {
4631 chplan_new[k].ChannelNum =
4632 chplan_ap.Channel[j];
4633 chplan_new[k].ScanType = SCAN_ACTIVE;
4634 i++;
4635 j++;
4636 k++;
4637 } else if (chplan_sta[i].ChannelNum <
4638 chplan_ap.Channel[j]) {
4639 chplan_new[k].ChannelNum =
4640 chplan_sta[i].ChannelNum;
4641 chplan_new[k].ScanType = SCAN_PASSIVE;
4642 i++;
4643 k++;
4644 } else if (chplan_sta[i].ChannelNum >
4645 chplan_ap.Channel[j]) {
4646 chplan_new[k].ChannelNum =
4647 chplan_ap.Channel[j];
4648 chplan_new[k].ScanType = SCAN_ACTIVE;
4649 j++;
4650 k++;
4652 } while (1);
4654 /* change AP not support channel to Passive scan */
4655 while (i < MAX_CHANNEL_NUM &&
4656 chplan_sta[i].ChannelNum != 0) {
4657 chplan_new[k].ChannelNum =
4658 chplan_sta[i].ChannelNum;
4659 chplan_new[k].ScanType = SCAN_PASSIVE;
4660 i++;
4661 k++;
4664 /* add channel AP supported */
4665 while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
4666 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4667 chplan_new[k].ScanType = SCAN_ACTIVE;
4668 j++;
4669 k++;
4671 } else {
4672 /* keep original STA 5G channel plan */
4673 while (i < MAX_CHANNEL_NUM &&
4674 chplan_sta[i].ChannelNum != 0) {
4675 chplan_new[k].ChannelNum =
4676 chplan_sta[i].ChannelNum;
4677 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4678 i++;
4679 k++;
4682 pmlmeext->update_channel_plan_by_ap_done = 1;
4685 /* If channel is used by AP, set channel scan type to active */
4686 channel = bssid->DSConfig;
4687 chplan_new = pmlmeext->channel_set;
4688 i = 0;
4689 while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
4690 if (chplan_new[i].ChannelNum == channel) {
4691 if (chplan_new[i].ScanType == SCAN_PASSIVE) {
4692 /* 5G Bnad 2, 3 (DFS) doesn't change
4693 to active scan */
4694 if (channel >= 52 && channel <= 144)
4695 break;
4697 chplan_new[i].ScanType = SCAN_ACTIVE;
4698 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4699 "%s: change channel %d scan type from passive to active\n",
4700 __func__, channel);
4702 break;
4704 i++;
4708 /****************************************************************************
4710 Following are the functions to report events
4712 *****************************************************************************/
4714 void report_survey_event23a(struct rtw_adapter *padapter,
4715 struct recv_frame *precv_frame)
4717 struct cmd_obj *pcmd_obj;
4718 u8 *pevtcmd;
4719 u32 cmdsz;
4720 struct survey_event *psurvey_evt;
4721 struct C2HEvent_Header *pc2h_evt_hdr;
4722 struct mlme_ext_priv *pmlmeext;
4723 struct cmd_priv *pcmdpriv;
4725 if (!padapter)
4726 return;
4728 pmlmeext = &padapter->mlmeextpriv;
4729 pcmdpriv = &padapter->cmdpriv;
4731 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4732 if (!pcmd_obj)
4733 return;
4735 cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
4736 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4737 if (!pevtcmd) {
4738 kfree(pcmd_obj);
4739 return;
4742 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4743 pcmd_obj->cmdsz = cmdsz;
4744 pcmd_obj->parmbuf = pevtcmd;
4746 pcmd_obj->rsp = NULL;
4747 pcmd_obj->rspsz = 0;
4749 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4750 pc2h_evt_hdr->len = sizeof(struct survey_event);
4751 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4752 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4754 psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4756 psurvey_evt->bss = collect_bss_info(padapter, precv_frame);
4757 if (!psurvey_evt->bss) {
4758 kfree(pcmd_obj);
4759 kfree(pevtcmd);
4760 return;
4763 process_80211d(padapter, psurvey_evt->bss);
4765 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4767 pmlmeext->sitesurvey_res.bss_cnt++;
4769 return;
4772 void report_surveydone_event23a(struct rtw_adapter *padapter)
4774 struct cmd_obj *pcmd_obj;
4775 u8 *pevtcmd;
4776 u32 cmdsz;
4777 struct surveydone_event *psurveydone_evt;
4778 struct C2HEvent_Header *pc2h_evt_hdr;
4779 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4780 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4782 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4783 if (!pcmd_obj)
4784 return;
4786 cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
4787 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4788 if (!pevtcmd) {
4789 kfree(pcmd_obj);
4790 return;
4793 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4794 pcmd_obj->cmdsz = cmdsz;
4795 pcmd_obj->parmbuf = pevtcmd;
4797 pcmd_obj->rsp = NULL;
4798 pcmd_obj->rspsz = 0;
4800 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4801 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4802 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4803 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4805 psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4806 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4808 DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
4810 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4812 return;
4815 void report_join_res23a(struct rtw_adapter *padapter, int res)
4817 struct cmd_obj *pcmd_obj;
4818 u8 *pevtcmd;
4819 u32 cmdsz;
4820 struct joinbss_event *pjoinbss_evt;
4821 struct C2HEvent_Header *pc2h_evt_hdr;
4822 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4823 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4824 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4826 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4827 if (!pcmd_obj)
4828 return;
4830 cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
4831 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4832 if (!pevtcmd) {
4833 kfree(pcmd_obj);
4834 return;
4837 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4838 pcmd_obj->cmdsz = cmdsz;
4839 pcmd_obj->parmbuf = pevtcmd;
4841 pcmd_obj->rsp = NULL;
4842 pcmd_obj->rspsz = 0;
4844 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4845 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4846 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4847 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4849 pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4850 memcpy((unsigned char *)&pjoinbss_evt->network.network,
4851 &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
4852 pjoinbss_evt->network.join_res = res;
4854 DBG_8723A("report_join_res23a(%d)\n", res);
4856 rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
4858 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4860 return;
4863 void report_del_sta_event23a(struct rtw_adapter *padapter,
4864 unsigned char *MacAddr, unsigned short reason)
4866 struct cmd_obj *pcmd_obj;
4867 u8 *pevtcmd;
4868 u32 cmdsz;
4869 struct sta_info *psta;
4870 int mac_id;
4871 struct stadel_event *pdel_sta_evt;
4872 struct C2HEvent_Header *pc2h_evt_hdr;
4873 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4874 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4876 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4877 if (!pcmd_obj)
4878 return;
4880 cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
4881 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4882 if (!pevtcmd) {
4883 kfree(pcmd_obj);
4884 return;
4887 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4888 pcmd_obj->cmdsz = cmdsz;
4889 pcmd_obj->parmbuf = pevtcmd;
4891 pcmd_obj->rsp = NULL;
4892 pcmd_obj->rspsz = 0;
4894 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4895 pc2h_evt_hdr->len = sizeof(struct stadel_event);
4896 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4897 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4899 pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4900 ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
4901 memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
4904 psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
4905 if (psta)
4906 mac_id = (int)psta->mac_id;
4907 else
4908 mac_id = -1;
4910 pdel_sta_evt->mac_id = mac_id;
4912 DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
4914 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4916 return;
4919 void report_add_sta_event23a(struct rtw_adapter *padapter,
4920 unsigned char *MacAddr, int cam_idx)
4922 struct cmd_obj *pcmd_obj;
4923 u8 *pevtcmd;
4924 u32 cmdsz;
4925 struct stassoc_event *padd_sta_evt;
4926 struct C2HEvent_Header *pc2h_evt_hdr;
4927 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4928 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4930 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4931 if (!pcmd_obj)
4932 return;
4934 cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
4935 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4936 if (!pevtcmd) {
4937 kfree(pcmd_obj);
4938 return;
4941 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4942 pcmd_obj->cmdsz = cmdsz;
4943 pcmd_obj->parmbuf = pevtcmd;
4945 pcmd_obj->rsp = NULL;
4946 pcmd_obj->rspsz = 0;
4948 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4949 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4950 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4951 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4953 padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4954 ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
4955 padd_sta_evt->cam_id = cam_idx;
4957 DBG_8723A("report_add_sta_event23a: add STA\n");
4959 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4961 return;
4964 /****************************************************************************
4966 Following are the event callback functions
4968 *****************************************************************************/
4970 /* for sta/adhoc mode */
4971 void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
4973 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4974 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4975 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4977 /* ERP */
4978 VCS_update23a(padapter, psta);
4980 /* HT */
4981 if (pmlmepriv->htpriv.ht_option) {
4982 psta->htpriv.ht_option = true;
4984 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4986 if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
4987 psta->htpriv.sgi = true;
4989 psta->qos_option = true;
4991 } else {
4992 psta->htpriv.ht_option = false;
4994 psta->htpriv.ampdu_enable = false;
4996 psta->htpriv.sgi = false;
4997 psta->qos_option = false;
5000 psta->htpriv.bwmode = pmlmeext->cur_bwmode;
5001 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
5003 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
5004 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
5006 /* QoS */
5007 if (pmlmepriv->qos_option)
5008 psta->qos_option = true;
5010 psta->state = _FW_LINKED;
5013 void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter,
5014 int join_res)
5016 struct sta_info *psta, *psta_bmc;
5017 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5018 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5019 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5020 struct sta_priv *pstapriv = &padapter->stapriv;
5022 if (join_res < 0) {
5023 hw_var_set_mlme_join(padapter, 1);
5024 hw_var_set_bssid(padapter, null_addr);
5026 /* restore to initial setting. */
5027 update_tx_basic_rate23a(padapter,
5028 padapter->registrypriv.wireless_mode);
5030 goto exit_mlmeext_joinbss_event_callback23a;
5033 if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
5034 /* for bc/mc */
5035 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
5036 if (psta_bmc) {
5037 pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
5038 update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
5039 Update_RA_Entry23a(padapter, psta_bmc);
5043 /* turn on dynamic functions */
5044 rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
5046 /* update IOT-releated issue */
5047 update_IOT_info23a(padapter);
5049 HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
5051 /* BCN interval */
5052 rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
5054 /* update capability */
5055 update_capinfo23a(padapter, pmlmeinfo->capability);
5057 /* WMM, Update EDCA param */
5058 WMMOnAssocRsp23a(padapter);
5060 /* HT */
5061 HTOnAssocRsp23a(padapter);
5063 /* Set cur_channel&cur_bwmode&cur_ch_offset */
5064 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5066 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
5067 if (psta) { /* only for infra. mode */
5068 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5070 /* DBG_8723A("set_sta_rate23a\n"); */
5072 psta->wireless_mode = pmlmeext->cur_wireless_mode;
5074 /* set per sta rate after updating HT cap. */
5075 set_sta_rate23a(padapter, psta);
5078 hw_var_set_mlme_join(padapter, 2);
5080 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
5081 /* correcting TSF */
5082 rtw_correct_TSF(padapter);
5084 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5087 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
5089 exit_mlmeext_joinbss_event_callback23a:
5090 DBG_8723A("=>%s\n", __func__);
5093 void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter,
5094 struct sta_info *psta)
5096 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5097 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5099 DBG_8723A("%s\n", __func__);
5101 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
5102 /* adhoc master or sta_count>1 */
5103 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5104 /* nothing to do */
5105 } else { /* adhoc client */
5106 /* correcting TSF */
5107 rtw_correct_TSF(padapter);
5109 /* start beacon */
5110 if (send_beacon23a(padapter) != _SUCCESS) {
5111 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5113 pmlmeinfo->state ^= MSR_ADHOC;
5115 return;
5118 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
5120 hw_var_set_mlme_join(padapter, 2);
5123 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5125 /* rate radaptive */
5126 Update_RA_Entry23a(padapter, psta);
5128 /* update adhoc sta_info */
5129 update_sta_info23a(padapter, psta);
5132 void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
5134 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5135 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5137 if (is_client_associated_to_ap23a(padapter) ||
5138 is_IBSS_empty23a(padapter)) {
5139 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5141 hw_var_set_mlme_disconnect(padapter);
5142 hw_var_set_bssid(padapter, null_addr);
5144 /* restore to initial setting. */
5145 update_tx_basic_rate23a(padapter,
5146 padapter->registrypriv.wireless_mode);
5148 /* switch to the 20M Hz mode after disconnect */
5149 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5150 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5152 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5153 pmlmeext->cur_ch_offset,
5154 pmlmeext->cur_bwmode);
5156 flush_all_cam_entry23a(padapter);
5158 pmlmeinfo->state = MSR_NOLINK;
5160 /* set MSR to no link state -> infra. mode */
5161 rtl8723a_set_media_status(padapter, MSR_INFRA);
5163 del_timer_sync(&pmlmeext->link_timer);
5167 static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
5169 u8 ret = false;
5171 if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) &&
5172 sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
5173 sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
5174 ret = false;
5175 else
5176 ret = true;
5178 sta_update_last_rx_pkts(psta);
5179 return ret;
5182 void linked_status_chk23a(struct rtw_adapter *padapter)
5184 u32 i;
5185 struct sta_info *psta;
5186 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5187 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5188 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5189 struct sta_priv *pstapriv = &padapter->stapriv;
5191 if (is_client_associated_to_ap23a(padapter)) {
5192 /* linked infrastructure client mode */
5194 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5195 int rx_chk_limit;
5197 rx_chk_limit = 4;
5199 psta = rtw_get_stainfo23a(pstapriv,
5200 pmlmeinfo->network.MacAddress);
5201 if (psta) {
5202 bool is_p2p_enable = false;
5204 if (chk_ap_is_alive(padapter, psta) == false)
5205 rx_chk = _FAIL;
5207 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5208 tx_chk = _FAIL;
5210 if (pmlmeext->active_keep_alive_check &&
5211 (rx_chk == _FAIL || tx_chk == _FAIL)) {
5212 u8 backup_oper_channel = 0;
5214 /* switch to correct channel of current
5215 network before issue keep-alive frames */
5216 if (rtw_get_oper_ch23a(padapter) !=
5217 pmlmeext->cur_channel) {
5218 backup_oper_channel =
5219 rtw_get_oper_ch23a(padapter);
5220 SelectChannel23a(padapter,
5221 pmlmeext->cur_channel);
5224 if (rx_chk != _SUCCESS)
5225 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
5227 if ((tx_chk != _SUCCESS &&
5228 pmlmeinfo->link_count++ == 0xf) ||
5229 rx_chk != _SUCCESS) {
5230 tx_chk = issue_nulldata23a(padapter,
5231 psta->hwaddr,
5232 0, 3, 1);
5233 /* if tx acked and p2p disabled,
5234 set rx_chk _SUCCESS to reset retry
5235 count */
5236 if (tx_chk == _SUCCESS &&
5237 !is_p2p_enable)
5238 rx_chk = _SUCCESS;
5241 /* back to the original operation channel */
5242 if (backup_oper_channel>0)
5243 SelectChannel23a(padapter,
5244 backup_oper_channel);
5245 } else {
5246 if (rx_chk != _SUCCESS) {
5247 if (pmlmeext->retry == 0) {
5248 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5249 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5250 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5254 if (tx_chk != _SUCCESS &&
5255 pmlmeinfo->link_count++ == 0xf)
5256 tx_chk = issue_nulldata23a(padapter,
5257 NULL, 0, 1,
5261 if (rx_chk == _FAIL) {
5262 pmlmeext->retry++;
5263 if (pmlmeext->retry > rx_chk_limit) {
5264 DBG_8723A_LEVEL(_drv_always_,
5265 "%s(%s): disconnect or "
5266 "roaming\n", __func__,
5267 padapter->pnetdev->name);
5268 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
5269 WLAN_REASON_EXPIRATION_CHK);
5270 return;
5272 } else
5273 pmlmeext->retry = 0;
5275 if (tx_chk == _FAIL)
5276 pmlmeinfo->link_count &= 0xf;
5277 else {
5278 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5279 pmlmeinfo->link_count = 0;
5283 } else if (is_client_associated_to_ibss23a(padapter)) {
5284 /* linked IBSS mode */
5285 /* for each assoc list entry to check the rx pkt counter */
5286 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5287 if (pmlmeinfo->FW_sta_info[i].status == 1) {
5288 psta = pmlmeinfo->FW_sta_info[i].psta;
5290 if (!psta)
5291 continue;
5293 if (pmlmeinfo->FW_sta_info[i].rx_pkt ==
5294 sta_rx_pkts(psta)) {
5296 if (pmlmeinfo->FW_sta_info[i].retry<3) {
5297 pmlmeinfo->FW_sta_info[i].retry++;
5298 } else {
5299 pmlmeinfo->FW_sta_info[i].retry = 0;
5300 pmlmeinfo->FW_sta_info[i].status = 0;
5301 report_del_sta_event23a(padapter, psta->hwaddr,
5302 65535/* indicate disconnect caused by no rx */
5305 } else {
5306 pmlmeinfo->FW_sta_info[i].retry = 0;
5307 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5311 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5315 static void survey_timer_hdl(unsigned long data)
5317 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5318 struct cmd_obj *ph2c;
5319 struct sitesurvey_parm *psurveyPara;
5320 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5321 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5323 /* issue rtw_sitesurvey_cmd23a */
5324 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5325 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
5326 pmlmeext->sitesurvey_res.channel_idx++;
5328 if (pmlmeext->scan_abort == true) {
5329 pmlmeext->sitesurvey_res.channel_idx =
5330 pmlmeext->sitesurvey_res.ch_num;
5331 DBG_8723A("%s idx:%d\n", __func__,
5332 pmlmeext->sitesurvey_res.channel_idx);
5334 pmlmeext->scan_abort = false;/* reset */
5337 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
5338 if (!ph2c)
5339 goto exit_survey_timer_hdl;
5341 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm),
5342 GFP_ATOMIC);
5343 if (!psurveyPara) {
5344 kfree(ph2c);
5345 goto exit_survey_timer_hdl;
5348 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
5349 GEN_CMD_CODE(_SiteSurvey));
5350 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
5353 exit_survey_timer_hdl:
5354 return;
5357 static void link_timer_hdl(unsigned long data)
5359 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5360 /* static unsigned int rx_pkt = 0; */
5361 /* static u64 tx_cnt = 0; */
5362 /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
5363 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5364 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5365 /* struct sta_priv *pstapriv = &padapter->stapriv; */
5367 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5368 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
5369 pmlmeinfo->state = MSR_NOLINK;
5370 report_join_res23a(padapter, -3);
5371 } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5372 /* re-auth timer */
5373 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5374 /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5375 /* */
5376 pmlmeinfo->state = 0;
5377 report_join_res23a(padapter, -1);
5378 return;
5379 /* */
5380 /* else */
5381 /* */
5382 /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5383 /* pmlmeinfo->reauth_count = 0; */
5384 /* */
5387 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
5388 pmlmeinfo->auth_seq = 1;
5389 issue_auth(padapter, NULL, 0);
5390 set_link_timer(pmlmeext, REAUTH_TO);
5391 } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5392 /* re-assoc timer */
5393 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5394 pmlmeinfo->state = MSR_NOLINK;
5395 report_join_res23a(padapter, -2);
5396 return;
5399 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
5400 issue_assocreq(padapter);
5401 set_link_timer(pmlmeext, REASSOC_TO);
5404 return;
5407 static void addba_timer_hdl(unsigned long data)
5409 struct sta_info *psta = (struct sta_info *)data;
5410 struct ht_priv *phtpriv;
5412 if (!psta)
5413 return;
5415 phtpriv = &psta->htpriv;
5417 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5418 if (phtpriv->candidate_tid_bitmap)
5419 phtpriv->candidate_tid_bitmap = 0x0;
5423 void init_addba_retry_timer23a(struct sta_info *psta)
5425 setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
5426 (unsigned long)psta);
5429 void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
5431 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5433 setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
5434 (unsigned long)padapter);
5436 setup_timer(&pmlmeext->link_timer, link_timer_hdl,
5437 (unsigned long)padapter);
5440 int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5442 return H2C_SUCCESS;
5445 int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5447 enum nl80211_iftype type;
5448 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5449 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5450 const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5452 switch (psetop->mode) {
5453 case NL80211_IFTYPE_P2P_GO:
5454 case NL80211_IFTYPE_AP:
5455 pmlmeinfo->state = MSR_AP;
5456 type = MSR_AP;
5457 break;
5458 case NL80211_IFTYPE_P2P_CLIENT:
5459 case NL80211_IFTYPE_STATION:
5460 /* clear state */
5461 pmlmeinfo->state &= ~(BIT(0)|BIT(1));
5462 /* set to STATION_STATE */
5463 pmlmeinfo->state |= MSR_INFRA;
5464 type = MSR_INFRA;
5465 break;
5466 case NL80211_IFTYPE_ADHOC:
5467 type = MSR_ADHOC;
5468 break;
5469 default:
5470 type = MSR_NOLINK;
5471 break;
5474 hw_var_set_opmode(padapter, type);
5475 /* Set_NETYPE0_MSR(padapter, type); */
5477 return H2C_SUCCESS;
5480 int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5482 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5483 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5484 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5485 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5486 /* u32 initialgain; */
5488 if (pparm->ifmode == NL80211_IFTYPE_AP ||
5489 pparm->ifmode == NL80211_IFTYPE_P2P_GO) {
5490 #ifdef CONFIG_8723AU_AP_MODE
5491 if (pmlmeinfo->state == MSR_AP) {
5492 /* todo: */
5493 return H2C_SUCCESS;
5495 #endif
5498 /* below is for ad-hoc master */
5499 if (pparm->ifmode == NL80211_IFTYPE_ADHOC) {
5500 rtw_joinbss_reset23a(padapter);
5502 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5503 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5504 pmlmeinfo->ERP_enable = 0;
5505 pmlmeinfo->WMM_enable = 0;
5506 pmlmeinfo->HT_enable = 0;
5507 pmlmeinfo->HT_caps_enable = 0;
5508 pmlmeinfo->HT_info_enable = 0;
5510 /* disable dynamic functions, such as high power, DIG */
5511 rtl8723a_odm_support_ability_backup(padapter);
5513 rtl8723a_odm_support_ability_clr(padapter,
5514 DYNAMIC_FUNC_DISABLE);
5516 /* cancel link timer */
5517 del_timer_sync(&pmlmeext->link_timer);
5519 /* clear CAM */
5520 flush_all_cam_entry23a(padapter);
5522 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5523 return H2C_PARAMETERS_ERROR;
5525 memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
5527 start_create_ibss(padapter);
5530 return H2C_SUCCESS;
5533 int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5535 struct registry_priv *pregpriv = &padapter->registrypriv;
5536 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5537 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5538 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5539 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5540 struct ieee80211_ht_operation *pht_info;
5541 u32 i;
5542 u8 *p;
5543 /* u32 initialgain; */
5544 /* u32 acparm; */
5546 /* check already connecting to AP or not */
5547 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5548 if (pmlmeinfo->state & MSR_INFRA)
5549 issue_deauth_ex(padapter, pnetwork->MacAddress,
5550 WLAN_REASON_DEAUTH_LEAVING, 5, 100);
5552 pmlmeinfo->state = MSR_NOLINK;
5554 /* clear CAM */
5555 flush_all_cam_entry23a(padapter);
5557 del_timer_sync(&pmlmeext->link_timer);
5559 /* set MSR to nolink -> infra. mode */
5560 rtl8723a_set_media_status(padapter, MSR_INFRA);
5562 hw_var_set_mlme_disconnect(padapter);
5565 rtw_joinbss_reset23a(padapter);
5567 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5568 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5569 pmlmeinfo->ERP_enable = 0;
5570 pmlmeinfo->WMM_enable = 0;
5571 pmlmeinfo->HT_enable = 0;
5572 pmlmeinfo->HT_caps_enable = 0;
5573 pmlmeinfo->HT_info_enable = 0;
5574 pmlmeinfo->bwmode_updated = false;
5575 /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
5577 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5578 return H2C_PARAMETERS_ERROR;
5580 memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
5582 /* Check AP vendor to move rtw_joinbss_cmd23a() */
5583 /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
5584 pnetwork->IELength); */
5586 for (i = 0; i < pnetwork->IELength;) {
5587 p = pnetwork->IEs + i;
5589 switch (p[0]) {
5590 case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
5591 if (!memcmp(p + 2, WMM_OUI23A, 4))
5592 pmlmeinfo->WMM_enable = 1;
5593 break;
5595 case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */
5596 pmlmeinfo->HT_caps_enable = 1;
5597 break;
5599 case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */
5600 pmlmeinfo->HT_info_enable = 1;
5602 /* spec case only for cisco's ap because cisco's ap
5603 * issue assoc rsp using mcs rate @40MHz or @20MHz */
5604 pht_info = (struct ieee80211_ht_operation *)(p + 2);
5606 if (pregpriv->cbw40_enable &&
5607 (pht_info->ht_param &
5608 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
5609 /* switch to the 40M Hz mode according to AP */
5610 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
5611 switch (pht_info->ht_param &
5612 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
5613 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
5614 pmlmeext->cur_ch_offset =
5615 HAL_PRIME_CHNL_OFFSET_LOWER;
5616 break;
5618 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
5619 pmlmeext->cur_ch_offset =
5620 HAL_PRIME_CHNL_OFFSET_UPPER;
5621 break;
5623 default:
5624 pmlmeext->cur_ch_offset =
5625 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5626 break;
5629 DBG_8723A("set ch/bw before connected\n");
5631 break;
5633 default:
5634 break;
5637 i += (p[1] + 2);
5640 hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
5641 hw_var_set_mlme_join(padapter, 0);
5643 /* cancel link timer */
5644 del_timer_sync(&pmlmeext->link_timer);
5646 start_clnt_join(padapter);
5648 return H2C_SUCCESS;
5651 int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5653 const struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5654 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5655 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5656 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5658 if (is_client_associated_to_ap23a(padapter)) {
5659 issue_deauth_ex(padapter, pnetwork->MacAddress,
5660 WLAN_REASON_DEAUTH_LEAVING,
5661 param->deauth_timeout_ms/100, 100);
5664 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5666 /* pmlmeinfo->state = MSR_NOLINK; */
5668 hw_var_set_mlme_disconnect(padapter);
5669 hw_var_set_bssid(padapter, null_addr);
5671 /* restore to initial setting. */
5672 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
5674 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC ||
5675 (pmlmeinfo->state & 0x03) == MSR_AP)
5676 rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */
5678 /* set MSR to no link state -> infra. mode */
5679 rtl8723a_set_media_status(padapter, MSR_INFRA);
5681 pmlmeinfo->state = MSR_NOLINK;
5683 /* switch to the 20M Hz mode after disconnect */
5684 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5685 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5687 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5688 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5690 flush_all_cam_entry23a(padapter);
5692 del_timer_sync(&pmlmeext->link_timer);
5694 rtw_free_uc_swdec_pending_queue23a(padapter);
5696 return H2C_SUCCESS;
5699 static int
5700 rtw_scan_ch_decision(struct rtw_adapter *padapter,
5701 struct rtw_ieee80211_channel *out, u32 out_num,
5702 const struct rtw_ieee80211_channel *in, u32 in_num)
5704 int i, j;
5705 int scan_ch_num = 0;
5706 int set_idx;
5707 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5709 /* clear out first */
5710 memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5712 /* acquire channels from in */
5713 j = 0;
5714 for (i = 0;i<in_num;i++) {
5715 if (in[i].hw_value &&
5716 !(in[i].flags & IEEE80211_CHAN_DISABLED) &&
5717 (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set,
5718 in[i].hw_value)) >= 0) {
5719 memcpy(&out[j], &in[i],
5720 sizeof(struct rtw_ieee80211_channel));
5722 if (pmlmeext->channel_set[set_idx].ScanType ==
5723 SCAN_PASSIVE)
5724 out[j].flags &= IEEE80211_CHAN_NO_IR;
5726 j++;
5728 if (j>= out_num)
5729 break;
5732 /* if out is empty, use channel_set as default */
5733 if (j == 0) {
5734 for (i = 0;i<pmlmeext->max_chan_nums;i++) {
5735 out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
5737 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5738 out[i].flags &= IEEE80211_CHAN_NO_IR;
5740 j++;
5744 if (padapter->setband == GHZ_24) { /* 2.4G */
5745 for (i = 0; i < j ; i++) {
5746 if (out[i].hw_value > 35)
5747 memset(&out[i], 0,
5748 sizeof(struct rtw_ieee80211_channel));
5749 else
5750 scan_ch_num++;
5752 j = scan_ch_num;
5753 } else if (padapter->setband == GHZ_50) { /* 5G */
5754 for (i = 0; i < j ; i++) {
5755 if (out[i].hw_value > 35) {
5756 memcpy(&out[scan_ch_num++], &out[i],
5757 sizeof(struct rtw_ieee80211_channel));
5760 j = scan_ch_num;
5761 } else
5764 return j;
5767 int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5769 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5770 const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
5771 u8 bdelayscan = false;
5772 u32 initialgain;
5773 u32 i;
5775 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5776 pmlmeext->sitesurvey_res.state = SCAN_START;
5777 pmlmeext->sitesurvey_res.bss_cnt = 0;
5778 pmlmeext->sitesurvey_res.channel_idx = 0;
5780 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5781 if (pparm->ssid[i].ssid_len) {
5782 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
5783 pparm->ssid[i].ssid,
5784 IEEE80211_MAX_SSID_LEN);
5785 pmlmeext->sitesurvey_res.ssid[i].ssid_len =
5786 pparm->ssid[i].ssid_len;
5787 } else {
5788 pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
5792 pmlmeext->sitesurvey_res.ch_num =
5793 rtw_scan_ch_decision(padapter,
5794 pmlmeext->sitesurvey_res.ch,
5795 RTW_CHANNEL_SCAN_AMOUNT,
5796 pparm->ch, pparm->ch_num);
5798 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5800 /* issue null data if associating to the AP */
5801 if (is_client_associated_to_ap23a(padapter)) {
5802 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5804 /* switch to correct channel of current network
5805 before issue keep-alive frames */
5806 if (rtw_get_oper_ch23a(padapter) !=
5807 pmlmeext->cur_channel)
5808 SelectChannel23a(padapter,
5809 pmlmeext->cur_channel);
5811 issue_nulldata23a(padapter, NULL, 1, 3, 500);
5813 bdelayscan = true;
5816 if (bdelayscan) {
5817 /* delay 50ms to protect nulldata(1). */
5818 set_survey_timer(pmlmeext, 50);
5819 return H2C_SUCCESS;
5823 if (pmlmeext->sitesurvey_res.state == SCAN_START ||
5824 pmlmeext->sitesurvey_res.state == SCAN_TXNULL) {
5825 /* disable dynamic functions, such as high power, DIG */
5826 rtl8723a_odm_support_ability_backup(padapter);
5827 rtl8723a_odm_support_ability_clr(padapter,
5828 DYNAMIC_FUNC_DISABLE);
5830 /* config the initial gain under scanning, need to
5831 write the BB registers */
5832 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
5833 initialgain = 0x30;
5834 else
5835 initialgain = 0x1E;
5837 rtl8723a_set_initial_gain(padapter, initialgain);
5839 /* set MSR to no link state */
5840 rtl8723a_set_media_status(padapter, MSR_NOLINK);
5842 rtl8723a_mlme_sitesurvey(padapter, 1);
5844 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5847 rtw_site_survey(padapter);
5849 return H2C_SUCCESS;
5852 int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5854 const struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
5855 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5856 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5858 if (pparm->mode < 4)
5859 pmlmeinfo->auth_algo = pparm->mode;
5861 return H2C_SUCCESS;
5864 int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5866 unsigned short ctrl;
5867 const struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
5868 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5869 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5870 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5872 /* main tx key for wep. */
5873 if (pparm->set_tx)
5874 pmlmeinfo->key_index = pparm->keyid;
5876 /* write cam */
5877 ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid;
5879 DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 "
5880 "WEP104-5 TKIP-2 AES-4) keyid:%d\n",
5881 pparm->algorithm, pparm->keyid);
5882 rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
5884 /* allow multicast packets to driver */
5885 rtl8723a_on_rcr_am(padapter);
5887 return H2C_SUCCESS;
5890 int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5892 u16 ctrl = 0;
5893 u8 cam_id;/* cam_entry */
5894 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5895 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5896 const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
5898 /* cam_entry: */
5899 /* 0~3 for default key */
5901 /* for concurrent mode (ap+sta): */
5902 /* default key is disable, using sw encrypt/decrypt */
5903 /* cam_entry = 4 for sta mode (macid = 0) */
5904 /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
5906 /* for concurrent mode (sta+sta): */
5907 /* default key is disable, using sw encrypt/decrypt */
5908 /* cam_entry = 4 mapping to macid = 0 */
5909 /* cam_entry = 5 mapping to macid = 2 */
5911 cam_id = 4;
5913 DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 "
5914 "WEP104-5 TKIP-2 AES-4) camid:%d\n",
5915 pparm->algorithm, cam_id);
5916 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
5917 struct sta_info *psta;
5918 struct sta_priv *pstapriv = &padapter->stapriv;
5920 if (pparm->algorithm == 0) { /* clear cam entry */
5921 clear_cam_entry23a(padapter, pparm->id);
5922 return H2C_SUCCESS_RSP;
5925 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
5926 if (psta) {
5927 ctrl = BIT(15) | (pparm->algorithm << 2);
5929 DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm "
5930 "=%d\n", pparm->algorithm);
5932 if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) {
5933 DBG_8723A("r871x_set_stakey_hdl23a():set_stakey"
5934 " failed, mac_id(aid) =%d\n",
5935 psta->mac_id);
5936 return H2C_REJECTED;
5939 /* 0~3 for default key, cmd_id = macid + 3,
5940 macid = aid+1; */
5941 cam_id = psta->mac_id + 3;
5943 DBG_8723A("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, "
5944 "cam_entry =%d\n", pparm->addr[0],
5945 pparm->addr[1], pparm->addr[2],
5946 pparm->addr[3], pparm->addr[4],
5947 pparm->addr[5], cam_id);
5949 rtl8723a_cam_write(padapter, cam_id, ctrl,
5950 pparm->addr, pparm->key);
5952 return H2C_SUCCESS_RSP;
5953 } else {
5954 DBG_8723A("r871x_set_stakey_hdl23a(): sta has been "
5955 "free\n");
5956 return H2C_REJECTED;
5960 /* below for sta mode */
5962 if (pparm->algorithm == 0) { /* clear cam entry */
5963 clear_cam_entry23a(padapter, pparm->id);
5964 return H2C_SUCCESS;
5967 ctrl = BIT(15) | (pparm->algorithm << 2);
5969 rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5971 pmlmeinfo->enc_algo = pparm->algorithm;
5973 return H2C_SUCCESS;
5976 int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5978 const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
5979 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5980 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5981 struct sta_info *psta;
5983 psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
5985 if (!psta)
5986 return H2C_SUCCESS;
5988 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
5989 pmlmeinfo->HT_enable) ||
5990 (pmlmeinfo->state & 0x03) == MSR_AP) {
5991 issue_action_BA23a(padapter, pparm->addr,
5992 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5993 mod_timer(&psta->addba_retry_timer,
5994 jiffies + msecs_to_jiffies(ADDBA_TO));
5995 } else
5996 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
5998 return H2C_SUCCESS;
6001 int set_tx_beacon_cmd23a(struct rtw_adapter *padapter)
6003 struct cmd_obj *ph2c;
6004 struct Tx_Beacon_param *ptxBeacon_parm;
6005 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6006 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6007 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6008 u8 res = _SUCCESS;
6009 int len_diff = 0;
6011 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
6012 if (!ph2c) {
6013 res = _FAIL;
6014 goto exit;
6017 ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
6018 if (!ptxBeacon_parm) {
6019 kfree(ph2c);
6020 res = _FAIL;
6021 goto exit;
6024 memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
6025 sizeof(struct wlan_bssid_ex));
6027 len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs,
6028 ptxBeacon_parm->network.IELength,
6029 pmlmeinfo->hidden_ssid_mode);
6030 ptxBeacon_parm->network.IELength += len_diff;
6032 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm,
6033 GEN_CMD_CODE(_TX_Beacon));
6035 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
6037 exit:
6038 return res;
6041 int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6043 u8 evt_code, evt_seq;
6044 u16 evt_sz;
6045 const struct C2HEvent_Header *c2h;
6046 void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf);
6048 c2h = (struct C2HEvent_Header *)pbuf;
6049 evt_sz = c2h->len;
6050 evt_seq = c2h->seq;
6051 evt_code = c2h->ID;
6053 /* checking if event code is valid */
6054 if (evt_code >= MAX_C2HEVT) {
6055 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6056 "Event Code(%d) mismatch!\n", evt_code);
6057 goto _abort_event_;
6060 /* checking if event size match the event parm size */
6061 if (wlanevents[evt_code].parmsize != 0 &&
6062 wlanevents[evt_code].parmsize != evt_sz) {
6063 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6064 "Event(%d) Parm Size mismatch (%d vs %d)!\n",
6065 evt_code, wlanevents[evt_code].parmsize, evt_sz);
6066 goto _abort_event_;
6069 event_callback = wlanevents[evt_code].event_callback;
6070 event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header));
6072 _abort_event_:
6074 return H2C_SUCCESS;
6077 int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6079 if (!pbuf)
6080 return H2C_PARAMETERS_ERROR;
6082 return H2C_SUCCESS;
6085 int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6087 if (send_beacon23a(padapter) == _FAIL) {
6088 DBG_8723A("issue_beacon23a, fail!\n");
6089 return H2C_PARAMETERS_ERROR;
6091 #ifdef CONFIG_8723AU_AP_MODE
6092 else { /* tx bc/mc frames after update TIM */
6093 struct sta_info *psta_bmc;
6094 struct list_head *plist, *phead, *ptmp;
6095 struct xmit_frame *pxmitframe;
6096 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6097 struct sta_priv *pstapriv = &padapter->stapriv;
6099 /* for BC/MC Frames */
6100 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
6101 if (!psta_bmc)
6102 return H2C_SUCCESS;
6104 if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) {
6105 msleep(10);/* 10ms, ATIM(HIQ) Windows */
6106 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
6107 spin_lock_bh(&pxmitpriv->lock);
6109 phead = get_list_head(&psta_bmc->sleep_q);
6111 list_for_each_safe(plist, ptmp, phead) {
6112 pxmitframe = container_of(plist,
6113 struct xmit_frame,
6114 list);
6116 list_del_init(&pxmitframe->list);
6118 psta_bmc->sleepq_len--;
6119 if (psta_bmc->sleepq_len>0)
6120 pxmitframe->attrib.mdata = 1;
6121 else
6122 pxmitframe->attrib.mdata = 0;
6124 pxmitframe->attrib.triggered = 1;
6126 pxmitframe->attrib.qsel = 0x11;/* HIQ */
6128 rtl8723au_hal_xmitframe_enqueue(padapter,
6129 pxmitframe);
6132 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
6133 spin_unlock_bh(&pxmitpriv->lock);
6136 #endif
6138 return H2C_SUCCESS;
6141 int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6143 const struct set_ch_parm *set_ch_parm;
6144 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6146 if (!pbuf)
6147 return H2C_PARAMETERS_ERROR;
6149 set_ch_parm = (struct set_ch_parm *)pbuf;
6151 DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__,
6152 padapter->pnetdev->name, set_ch_parm->ch,
6153 set_ch_parm->bw, set_ch_parm->ch_offset);
6155 pmlmeext->cur_channel = set_ch_parm->ch;
6156 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6157 pmlmeext->cur_bwmode = set_ch_parm->bw;
6159 set_channel_bwmode23a(padapter, set_ch_parm->ch,
6160 set_ch_parm->ch_offset, set_ch_parm->bw);
6162 return H2C_SUCCESS;
6165 int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6167 const struct SetChannelPlan_param *setChannelPlan_param;
6168 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6170 if (!pbuf)
6171 return H2C_PARAMETERS_ERROR;
6173 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6175 pmlmeext->max_chan_nums =
6176 init_channel_set(padapter, setChannelPlan_param->channel_plan,
6177 pmlmeext->channel_set);
6178 init_channel_list(padapter, pmlmeext->channel_set,
6179 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6181 return H2C_SUCCESS;
6184 int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6186 struct LedBlink_param *ledBlink_param;
6188 if (!pbuf)
6189 return H2C_PARAMETERS_ERROR;
6191 ledBlink_param = (struct LedBlink_param *)pbuf;
6193 return H2C_SUCCESS;
6196 int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6198 return H2C_REJECTED;
6201 /* TDLS_WRCR : write RCR DATA BIT */
6202 /* TDLS_SD_PTI : issue peer traffic indication */
6203 /* TDLS_CS_OFF : go back to the channel linked with AP,
6204 terminating channel switch procedure */
6205 /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and
6206 mgnt frame */
6207 /* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */
6208 /* TDLS_OFF_CH : first time set channel to off channel */
6209 /* TDLS_BASE_CH : go back tp the channel linked with AP when set
6210 base channel as target channel */
6211 /* TDLS_P_OFF_CH : periodically go to off channel */
6212 /* TDLS_P_BASE_CH : periodically go back to base channel */
6213 /* TDLS_RS_RCR : restore RCR */
6214 /* TDLS_CKALV_PH1 : check alive timer phase1 */
6215 /* TDLS_CKALV_PH2 : check alive timer phase2 */
6216 /* TDLS_FREE_STA : free tdls sta */
6217 int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6219 return H2C_REJECTED;