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
14 ******************************************************************************/
15 #define _RTW_MLME_EXT_C_
17 #include <osdep_service.h>
18 #include <drv_types.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);
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 /*----------------------------------------------------------
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 /********************************************************
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 */
149 static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
150 /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */
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*/
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},
303 {0, &dummy_event_callback},
307 {0, &dummy_event_callback},
312 static void rtw_correct_TSF(struct rtw_adapter *padapter)
314 hw_var_set_correct_tsf(padapter);
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)
334 for (i = 0; ch_set[i]. ChannelNum != 0; i++) {
335 if (ch == ch_set[i].ChannelNum)
339 if (i >= ch_set[i].ChannelNum)
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);
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;
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;
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;
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) {
423 for (i = 0; i < chanset_size; i++) {
424 if (channel_set[i].ChannelNum == chan)
431 static void init_channel_list(struct rtw_adapter *padapter,
432 struct rt_channel_info *channel_set,
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 }
453 for (op = 0; op_class[op].op_class; op++) {
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))
462 if ((0 == padapter->registrypriv.ht_enable) &&
466 if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
467 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
471 reg = &channel_list->reg_class[cla];
473 reg->reg_class = o->op_class;
476 reg->channel[reg->channels] = ch;
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)
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);
498 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
500 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
501 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
503 Index2G = RTW_ChannelPlanMap[cplan].Index2G;
506 if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
508 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
509 Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
511 Index5G = RTW_ChannelPlanMap[cplan].Index5G;
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;
535 c_set[ch_size].ScanType = SCAN_PASSIVE;
537 c_set[ch_size].ScanType = SCAN_ACTIVE;
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 =
554 c_set[ch_size].ScanType =
556 DBG_8723A("%s(): channel_set[%d].ChannelNum = "
557 "%d\n", __func__, ch_size,
558 c_set[ch_size].ChannelNum);
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);
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;
598 void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext)
600 struct rtw_adapter *padapter = pmlmeext->padapter;
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); */
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;
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))
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;
643 if (!ieee80211_is_mgmt(mgmt->frame_control))
646 /* receive the frames that ra(a1) is my address or ra(a1) is
648 if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) &&
649 !is_broadcast_ether_addr(mgmt->da))
652 ptable = mlme_sta_tbl;
654 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
658 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
659 "Currently we do not support reserved sub-fr-type =%d\n",
665 psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa);
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);
678 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
681 #ifdef CONFIG_8723AU_AP_MODE
683 case IEEE80211_STYPE_AUTH:
684 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
685 ptable->func = &OnAuth23a;
687 ptable->func = &OnAuth23aClient23a;
689 case IEEE80211_STYPE_ASSOC_REQ:
690 case IEEE80211_STYPE_REASSOC_REQ:
691 _mgt_dispatcher23a(padapter, ptable, precv_frame);
693 case IEEE80211_STYPE_PROBE_REQ:
694 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
695 _mgt_dispatcher23a(padapter, ptable, precv_frame);
697 _mgt_dispatcher23a(padapter, ptable, precv_frame);
699 case IEEE80211_STYPE_BEACON:
700 _mgt_dispatcher23a(padapter, ptable, precv_frame);
702 case IEEE80211_STYPE_ACTION:
703 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
704 _mgt_dispatcher23a(padapter, ptable, precv_frame);
707 _mgt_dispatcher23a(padapter, ptable, precv_frame);
711 _mgt_dispatcher23a(padapter, ptable, precv_frame);
715 /****************************************************************************
717 Following are the callback functions for each subtype of the management frames
719 *****************************************************************************/
722 OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
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;
733 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
736 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
737 !check_fwstate(pmlmepriv,
738 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
741 if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) {
742 printk(KERN_WARNING "%s: Received non probe request frame\n",
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 */
755 if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) ||
756 (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) {
760 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
761 pmlmepriv->cur_network.join_res)
762 issue_probersp(padapter, mgmt->sa);
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);
782 OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
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;
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",
816 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
817 report_survey_event23a(padapter, precv_frame);
821 if (!ether_addr_equal(mgmt->bssid,
822 get_my_bssid23a(&pmlmeinfo->network)))
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);
830 update_network23a(&pmlmepriv->cur_network.network, pbss,
832 rtw_get_bcn_info23a(&pmlmepriv->cur_network);
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);
845 start_clnt_auth(padapter);
850 if (((pmlmeinfo->state & 0x03) == MSR_AP) &&
851 (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
852 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
854 ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len);
855 if (ret != _SUCCESS) {
856 DBG_8723A_LEVEL(_drv_always_, "ap has changed, "
858 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
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,
870 } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
871 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
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,
882 /* allocate a new CAM entry for IBSS station */
883 cam_idx = allocate_fw_sta_entry23a(padapter);
884 if (cam_idx == NUM_STA)
887 /* get supported rate */
888 if (update_sta_support_rate23a(padapter, pie, pie_len,
890 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
894 /* update TSF Value */
895 rtw_update_TSF(pmlmeext, mgmt);
897 /* report sta add event */
898 report_add_sta_event23a(padapter, mgmt->sa,
908 #ifdef CONFIG_8723AU_AP_MODE
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;
923 u16 auth_mode, seq, algorithm;
924 int status, len = skb->len;
926 if ((pmlmeinfo->state & 0x03) != MSR_AP)
929 DBG_8723A("+OnAuth23a\n");
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)
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;
962 if (rtw_access_ctrl23a(padapter, sa) == false) {
963 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
967 pstat = rtw_get_stainfo23a(pstapriv, sa);
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);
973 DBG_8723A(" Exceed the upper limit of supported "
975 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
979 pstat->state = WIFI_FW_AUTH_NULL;
982 /* pstat->flags = 0; */
983 /* pstat->capability = 0; */
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);
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;
1017 if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) {
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;
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;
1030 } else { /* shared system or auto authentication */
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 "
1045 status = WLAN_STATUS_CHALLENGE_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;
1055 DBG_8723A("auth rejected because challenge "
1057 status = WLAN_STATUS_CHALLENGE_FAIL;
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;
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;
1082 rtw_free_stainfo23a(padapter, pstat);
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);
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;
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))
1114 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
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);
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;
1131 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1132 /* pmlmeinfo->reauth_count = 0; */
1135 set_link_timer(pmlmeext, 1);
1140 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1141 /* legendary shared system */
1142 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen);
1145 /* DBG_8723A("marc: no challenge text?\n"); */
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);
1159 } else if (seq == 4) {
1160 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1165 /* this is also illegal */
1166 /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n",
1172 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
1173 start_clnt_assoc(padapter);
1179 /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1184 #ifdef CONFIG_8723AU_AP_MODE
1185 static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen)
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
1193 DBG_8723A("short vendor specific information element "
1194 "ignored (len =%i)\n", elen);
1198 oui = RTW_GET_BE24(pos);
1200 case WLAN_OUI_MICROSOFT:
1201 /* Microsoft/Wi-Fi information elements are further typed and
1204 case WLAN_OUI_TYPE_MICROSOFT_WPA:
1205 /* Microsoft OUI (00:50:F2) with OUI Type 1:
1206 * real WPA information element */
1208 case WLAN_OUI_TYPE_MICROSOFT_WMM:
1210 DBG_8723A("short WME information element "
1211 "ignored (len =%i)\n", elen);
1215 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
1216 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
1218 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
1221 DBG_8723A("unknown WME information element "
1222 "ignored (subtype =%d len =%i)\n",
1227 case WLAN_OUI_TYPE_MICROSOFT_WPS:
1228 /* Wi-Fi Protected Setup (WPS) IE */
1231 DBG_8723A("Unknown Microsoft information element "
1232 "ignored (type =%d len =%i)\n",
1240 case VENDOR_HT_CAPAB_OUI_TYPE:
1243 DBG_8723A("Unknown Broadcom information element "
1244 "ignored (type =%d len =%i)\n", pos[3], elen);
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);
1259 static int rtw_validate_frame_ies(const u8 *start, uint len)
1261 const u8 *pos = start;
1273 DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d "
1274 "left =%i)\n", __func__, id, elen, left);
1280 case WLAN_EID_SUPP_RATES:
1281 case WLAN_EID_FH_PARAMS:
1282 case WLAN_EID_DS_PARAMS:
1283 case WLAN_EID_CF_PARAMS:
1285 case WLAN_EID_IBSS_PARAMS:
1286 case WLAN_EID_CHALLENGE:
1287 case WLAN_EID_ERP_INFO:
1288 case WLAN_EID_EXT_SUPP_RATES:
1290 case WLAN_EID_VENDOR_SPECIFIC:
1291 if (rtw_validate_vendor_specific_ies(pos, elen))
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:
1304 DBG_8723A("%s IEEE 802.11 ignored unknown element "
1305 "(id =%d elen =%d)\n", __func__, id, elen);
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];
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;
1344 if ((pmlmeinfo->state & 0x03) != MSR_AP)
1347 left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
1348 if (ieee80211_is_assoc_req(mgmt->frame_control)) {
1350 pos = mgmt->u.assoc_req.variable;
1351 left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
1352 } else { /* WIFI_REASSOCREQ */
1354 pos = mgmt->u.reassoc_req.variable;
1355 left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable);
1359 DBG_8723A("handle_assoc(reassoc =%d) - too short payload "
1360 "(len =%lu)\n", reassoc, (unsigned long)pkt_len);
1364 pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa);
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);
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;
1384 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1385 pstat->state |= WIFI_FW_ASSOC_STATE;
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",
1399 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1400 goto OnAssocReq23aFail;
1403 /* now we should check all the fields... */
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",
1410 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1411 goto OnAssocReq23aFail;
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);
1427 DBG_8723A("Rx a sta assoc-req which supported rate is "
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;
1436 memcpy(supportRate, p + 2, p[1]);
1437 supportRateNum = p[1];
1439 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left);
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;
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);
1467 wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1468 WLAN_OUI_TYPE_MICROSOFT_WPA,
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,
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;
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,
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;
1501 status = WLAN_STATUS_INVALID_IE;
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,
1526 DBG_8723A("STA included WPS IE in (Re)Association "
1527 "Request - assume WPS is used\n");
1528 pstat->flags |= WLAN_STA_WPS;
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;
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",
1541 status = WLAN_STATUS_INVALID_IE;
1543 goto OnAssocReq23aFail;
1547 DBG_8723A("STA included WPS IE in (Re)Association "
1548 "Request - WPS is used\n");
1549 pstat->flags |= WLAN_STA_WPS;
1552 copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ?
1553 sizeof(pstat->wpa_ie) : (wpa_ie_len + 2);
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;
1576 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1577 WLAN_OUI_TYPE_MICROSOFT_WMM,
1580 pstat->flags |= WLAN_STA_WME;
1582 pstat->qos_option = 1;
1583 pstat->qos_info = *(p + 8);
1586 (pstat->qos_info >> 5) & 0x3;
1588 if ((pstat->qos_info & 0xf) != 0xf)
1589 pstat->has_legacy_ac = true;
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);
1597 pstat->uapsd_vo = 0;
1599 if (pstat->qos_info & BIT(1))
1600 pstat->uapsd_vi = BIT(0)|BIT(1);
1602 pstat->uapsd_vi = 0;
1604 if (pstat->qos_info & BIT(2))
1605 pstat->uapsd_bk = BIT(0)|BIT(1);
1607 pstat->uapsd_bk = 0;
1609 if (pstat->qos_info & BIT(3))
1610 pstat->uapsd_be = BIT(0)|BIT(1);
1612 pstat->uapsd_be = 0;
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));
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",
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;
1660 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1661 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
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);
1678 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1679 if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1682 if (pstat->aid > NUM_STA)
1683 pstat->aid = NUM_STA;
1684 if (pstat->aid > pstapriv->max_num_sta) {
1688 DBG_8723A(" no room for more AIDs\n");
1690 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1692 goto OnAssocReq23aFail;
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 /* 1 bss_cap_update & sta_info_update23a */
1721 bss_cap_update_on_sta_join23a(padapter, pstat);
1722 sta_info_update23a(padapter, pstat);
1724 /* issue assoc rsp before notify station join event. */
1725 if (ieee80211_is_assoc_req(mgmt->frame_control))
1726 issue_assocrsp(padapter, status, pstat,
1727 IEEE80211_STYPE_ASSOC_RESP);
1729 issue_assocrsp(padapter, status, pstat,
1730 IEEE80211_STYPE_REASSOC_RESP);
1732 /* 2 - report to upper layer */
1733 DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
1734 rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1736 /* 3-(1) report sta add event */
1737 report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid);
1744 issue_deauth23a(padapter, mgmt->sa, status);
1750 if (ieee80211_is_assoc_req(mgmt->frame_control))
1751 issue_assocrsp(padapter, status, pstat,
1752 IEEE80211_STYPE_ASSOC_RESP);
1754 issue_assocrsp(padapter, status, pstat,
1755 IEEE80211_STYPE_REASSOC_RESP);
1757 #endif /* CONFIG_8723AU_AP_MODE */
1763 OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1765 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1766 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1767 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1768 struct sk_buff *skb = precv_frame->pkt;
1769 struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
1771 unsigned short status;
1773 u8 *pframe = skb->data;
1774 int pkt_len = skb->len;
1777 DBG_8723A("%s\n", __func__);
1779 /* check A1 matches or not */
1780 if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da))
1783 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1786 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1789 del_timer_sync(&pmlmeext->link_timer);
1792 status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
1794 DBG_8723A("assoc reject, status code: %d\n", status);
1795 pmlmeinfo->state = MSR_NOLINK;
1797 goto report_assoc_result;
1800 /* get capabilities */
1801 pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info);
1804 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
1807 res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
1809 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1811 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1813 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
1814 pmgmt->u.assoc_resp.variable, pielen);
1816 HT_caps_handler23a(padapter, p);
1818 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
1819 pmgmt->u.assoc_resp.variable, pielen);
1821 HT_info_handler23a(padapter, p);
1823 p = cfg80211_find_ie(WLAN_EID_ERP_INFO,
1824 pmgmt->u.assoc_resp.variable, pielen);
1826 ERP_IE_handler23a(padapter, p);
1828 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1830 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1831 WLAN_OUI_TYPE_MICROSOFT_WMM,
1832 pie, pframe + pkt_len - pie);
1837 /* if this IE is too short, try the next */
1840 /* if this IE is WMM params, we found what we wanted */
1846 WMM_param_handler23a(padapter, p);
1848 pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
1849 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1851 /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1852 UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates);
1854 report_assoc_result:
1855 pmlmepriv->assoc_rsp_len = 0;
1857 kfree(pmlmepriv->assoc_rsp);
1858 pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC);
1859 if (pmlmepriv->assoc_rsp) {
1860 memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len);
1861 pmlmepriv->assoc_rsp_len = pkt_len;
1864 kfree(pmlmepriv->assoc_rsp);
1866 report_join_res23a(padapter, res);
1872 OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1874 unsigned short reason;
1875 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1876 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1877 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1878 struct sk_buff *skb = precv_frame->pkt;
1879 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1881 if (!ether_addr_equal(mgmt->bssid,
1882 get_my_bssid23a(&pmlmeinfo->network)))
1885 reason = le16_to_cpu(mgmt->u.deauth.reason_code);
1887 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1889 #ifdef CONFIG_8723AU_AP_MODE
1890 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1891 struct sta_info *psta;
1892 struct sta_priv *pstapriv = &padapter->stapriv;
1894 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
1895 "sta:%pM\n", reason, mgmt->sa);
1897 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1901 spin_lock_bh(&pstapriv->asoc_list_lock);
1902 if (!list_empty(&psta->asoc_list)) {
1903 list_del_init(&psta->asoc_list);
1904 pstapriv->asoc_list_cnt--;
1905 updated = ap_free_sta23a(padapter, psta,
1908 spin_unlock_bh(&pstapriv->asoc_list_lock);
1910 associated_clients_update23a(padapter, updated);
1917 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
1918 "sta:%pM\n", reason, mgmt->bssid);
1920 receive_disconnect23a(padapter, mgmt->bssid, reason);
1922 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1928 OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1930 unsigned short reason;
1931 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1932 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1933 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1934 struct sk_buff *skb = precv_frame->pkt;
1935 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1937 if (!ether_addr_equal(mgmt->bssid,
1938 get_my_bssid23a(&pmlmeinfo->network)))
1941 reason = le16_to_cpu(mgmt->u.disassoc.reason_code);
1943 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1945 #ifdef CONFIG_8723AU_AP_MODE
1946 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1947 struct sta_info *psta;
1948 struct sta_priv *pstapriv = &padapter->stapriv;
1950 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
1951 " sta:%pM\n", reason, mgmt->sa);
1953 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1957 spin_lock_bh(&pstapriv->asoc_list_lock);
1958 if (!list_empty(&psta->asoc_list)) {
1959 list_del_init(&psta->asoc_list);
1960 pstapriv->asoc_list_cnt--;
1961 updated = ap_free_sta23a(padapter, psta,
1964 spin_unlock_bh(&pstapriv->asoc_list_lock);
1966 associated_clients_update23a(padapter, updated);
1973 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
1974 "code(%d) sta:%pM\n", reason, mgmt->bssid);
1976 receive_disconnect23a(padapter, mgmt->bssid, reason);
1978 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1983 OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1985 DBG_8723A("%s\n", __func__);
1990 on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1996 OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2002 OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2007 static int OnAction23a_back23a(struct rtw_adapter *padapter,
2008 struct recv_frame *precv_frame)
2011 struct sta_info *psta = NULL;
2012 struct recv_reorder_ctrl *preorder_ctrl;
2013 unsigned char category, action;
2014 unsigned short tid, status, capab, params, reason_code = 0;
2015 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2016 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2017 struct sk_buff *skb = precv_frame->pkt;
2018 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2019 struct sta_priv *pstapriv = &padapter->stapriv;
2021 /* check RA matches or not */
2022 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
2025 DBG_8723A("%s\n", __func__);
2027 if ((pmlmeinfo->state&0x03) != MSR_AP)
2028 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2032 psta = rtw_get_stainfo23a(pstapriv, addr);
2037 category = mgmt->u.action.category;
2038 if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */
2039 if (!pmlmeinfo->HT_enable)
2041 /* action_code is located in the same place for all
2042 action events, so pick any */
2043 action = mgmt->u.action.u.wme_action.action_code;
2044 DBG_8723A("%s, action =%d\n", __func__, action);
2046 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
2047 memcpy(&pmlmeinfo->ADDBA_req,
2048 &mgmt->u.action.u.addba_req.dialog_token,
2049 sizeof(struct ADDBA_request));
2050 process_addba_req23a(padapter,
2051 (u8 *)&pmlmeinfo->ADDBA_req, addr);
2052 if (pmlmeinfo->bAcceptAddbaReq == true)
2053 issue_action_BA23a(padapter, addr,
2054 WLAN_ACTION_ADDBA_RESP, 0);
2056 /* reject ADDBA Req */
2057 issue_action_BA23a(padapter, addr,
2058 WLAN_ACTION_ADDBA_RESP, 37);
2061 case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
2062 status = get_unaligned_le16(
2063 &mgmt->u.action.u.addba_resp.status);
2064 capab = get_unaligned_le16(
2065 &mgmt->u.action.u.addba_resp.capab);
2066 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
2067 if (status == 0) { /* successful */
2068 DBG_8723A("agg_enable for TID =%d\n", tid);
2069 psta->htpriv.agg_enable_bitmap |= BIT(tid);
2070 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2072 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2075 case WLAN_ACTION_DELBA: /* DELBA */
2076 params = get_unaligned_le16(
2077 &mgmt->u.action.u.delba.params);
2080 if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
2081 preorder_ctrl = &psta->recvreorder_ctrl[tid];
2082 preorder_ctrl->enable = false;
2083 preorder_ctrl->indicate_seq = 0xffff;
2085 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2086 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2088 reason_code = get_unaligned_le16(
2089 &mgmt->u.action.u.delba.reason_code);
2090 /* todo: how to notify the host while receiving
2100 static int on_action_public23a(struct rtw_adapter *padapter,
2101 struct recv_frame *precv_frame)
2103 struct sk_buff *skb = precv_frame->pkt;
2104 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2105 u8 *pframe = skb->data;
2108 /* check RA matches or not */
2109 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
2112 channel = rtw_get_oper_ch23a(padapter);
2114 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2115 freq = ieee80211_channel_to_frequency(channel,
2116 IEEE80211_BAND_2GHZ);
2118 freq = ieee80211_channel_to_frequency(channel,
2119 IEEE80211_BAND_5GHZ);
2121 if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
2129 OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2135 OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2141 OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2147 OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2151 struct action_handler *ptable;
2152 struct sk_buff *skb = precv_frame->pkt;
2153 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2155 category = mgmt->u.action.category;
2158 i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) {
2159 ptable = &OnAction23a_tbl[i];
2161 if (category == ptable->num)
2162 ptable->func(padapter, precv_frame);
2168 static int DoReserved23a(struct rtw_adapter *padapter,
2169 struct recv_frame *precv_frame)
2174 struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
2176 struct xmit_frame *pmgntframe;
2177 struct xmit_buf *pxmitbuf;
2179 pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
2182 DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__,
2183 pxmitpriv->adapter->pnetdev->name);
2187 pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
2189 DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__,
2190 pxmitpriv->adapter->pnetdev->name);
2191 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
2196 pmgntframe->frame_tag = MGNT_FRAMETAG;
2197 pmgntframe->pxmitbuf = pxmitbuf;
2198 pmgntframe->buf_addr = pxmitbuf->pbuf;
2199 pxmitbuf->priv_data = pmgntframe;
2205 /****************************************************************************
2207 Following are some TX functions for WiFi MLME
2209 *****************************************************************************/
2211 void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
2213 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2215 pmlmeext->tx_rate = rate;
2216 DBG_8723A("%s(): rate = %x\n", __func__, rate);
2219 void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
2220 struct pkt_attrib *pattrib)
2222 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2224 memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
2226 pattrib->hdrlen = 24;
2227 pattrib->nr_frags = 1;
2228 pattrib->priority = 7;
2229 pattrib->mac_id = 0;
2230 pattrib->qsel = 0x12;
2232 pattrib->pktlen = 0;
2234 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
2235 pattrib->raid = 6;/* b mode */
2237 pattrib->raid = 5;/* a/g mode */
2239 pattrib->encrypt = 0;
2240 pattrib->bswenc = false;
2242 pattrib->qos_en = false;
2243 pattrib->ht_en = false;
2244 pattrib->bwmode = HT_CHANNEL_WIDTH_20;
2245 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2246 pattrib->sgi = false;
2248 pattrib->seqnum = pmlmeext->mgnt_seq;
2250 pattrib->retry_ctrl = true;
2253 void dump_mgntframe23a(struct rtw_adapter *padapter,
2254 struct xmit_frame *pmgntframe)
2256 if (padapter->bSurpriseRemoved == true ||
2257 padapter->bDriverStopped == true)
2260 rtl8723au_mgnt_xmit(padapter, pmgntframe);
2263 int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
2264 struct xmit_frame *pmgntframe, int timeout_ms)
2268 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2269 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2270 struct submit_ctx sctx;
2272 if (padapter->bSurpriseRemoved == true ||
2273 padapter->bDriverStopped == true)
2276 rtw_sctx_init23a(&sctx, timeout_ms);
2277 pxmitbuf->sctx = &sctx;
2279 ret = rtl8723au_mgnt_xmit(padapter, pmgntframe);
2281 if (ret == _SUCCESS)
2282 ret = rtw_sctx_wait23a(&sctx);
2284 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2285 pxmitbuf->sctx = NULL;
2286 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2291 int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
2292 struct xmit_frame *pmgntframe)
2295 u32 timeout_ms = 500;/* 500ms */
2296 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2298 if (padapter->bSurpriseRemoved == true ||
2299 padapter->bDriverStopped == true)
2302 mutex_lock(&pxmitpriv->ack_tx_mutex);
2303 pxmitpriv->ack_tx = true;
2305 pmgntframe->ack_report = 1;
2306 if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2307 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
2309 pxmitpriv->ack_tx = false;
2310 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2315 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2323 ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
2325 /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n",
2326 __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
2328 if (ssid_ie && ssid_len_ori > 0) {
2329 switch (hidden_ssid_mode) {
2331 next_ie = ssid_ie + 2 + ssid_len_ori;
2332 remain_len = ies_len -(next_ie-ies);
2335 memcpy(ssid_ie+2, next_ie, remain_len);
2336 len_diff -= ssid_len_ori;
2340 memset(&ssid_ie[2], 0, ssid_len_ori);
2350 void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
2352 struct xmit_frame *pmgntframe;
2353 struct pkt_attrib *pattrib;
2354 unsigned char *pframe;
2355 struct ieee80211_mgmt *mgmt;
2356 unsigned int rate_len;
2357 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2358 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2359 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2360 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2361 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2362 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2367 /* DBG_8723A("%s\n", __func__); */
2369 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2371 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2374 #ifdef CONFIG_8723AU_AP_MODE
2375 spin_lock_bh(&pmlmepriv->bcn_update_lock);
2378 /* update attribute */
2379 pattrib = &pmgntframe->attrib;
2380 update_mgntframe_attrib23a(padapter, pattrib);
2381 pattrib->qsel = 0x10;
2383 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2385 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2386 mgmt = (struct ieee80211_mgmt *)pframe;
2388 mgmt->frame_control =
2389 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
2392 ether_addr_copy(mgmt->da, bc_addr);
2393 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2394 ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
2396 /* timestamp will be inserted by hardware */
2398 put_unaligned_le16(cur_network->beacon_interval,
2399 &mgmt->u.beacon.beacon_int);
2401 put_unaligned_le16(cur_network->capability,
2402 &mgmt->u.beacon.capab_info);
2404 pframe = mgmt->u.beacon.variable;
2405 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
2407 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2410 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
2411 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2412 len_diff = update_hidden_ssid(pframe, cur_network->IELength,
2413 pmlmeinfo->hidden_ssid_mode);
2414 pframe += (cur_network->IELength+len_diff);
2415 pattrib->pktlen += (cur_network->IELength+len_diff);
2417 iebuf = mgmt->u.beacon.variable;
2418 buflen = pattrib->pktlen -
2419 offsetof(struct ieee80211_mgmt, u.beacon.variable);
2420 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2421 WLAN_OUI_TYPE_MICROSOFT_WPS,
2424 if (wps_ie && wps_ie[1] > 0) {
2425 rtw_get_wps_attr_content23a(wps_ie, wps_ie[1],
2426 WPS_ATTR_SELECTED_REGISTRAR,
2430 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2432 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2438 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2439 cur_network->Ssid.ssid_len,
2440 cur_network->Ssid.ssid, &pattrib->pktlen);
2442 /* supported rates... */
2443 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2444 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2445 ((rate_len > 8)? 8: rate_len),
2446 cur_network->SupportedRates, &pattrib->pktlen);
2448 /* DS parameter set */
2449 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
2450 &cur_network->DSConfig, &pattrib->pktlen);
2452 /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */
2456 /* IBSS Parameter Set... */
2457 /* ATIMWindow = cur->ATIMWindow; */
2459 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2460 (unsigned char *)&ATIMWindow,
2464 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2465 &erpinfo, &pattrib->pktlen);
2468 /* EXTERNDED SUPPORTED RATE */
2470 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2472 cur_network->SupportedRates + 8,
2475 /* todo:HT for adhoc */
2479 #ifdef CONFIG_8723AU_AP_MODE
2480 pmlmepriv->update_bcn = false;
2482 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2485 if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
2486 DBG_8723A("beacon frame too large\n");
2490 pattrib->last_txcmdsz = pattrib->pktlen;
2492 /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
2494 dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
2496 dump_mgntframe23a(padapter, pmgntframe);
2499 static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da)
2501 struct xmit_frame *pmgntframe;
2502 struct pkt_attrib *pattrib;
2503 unsigned char *pframe;
2504 struct ieee80211_mgmt *mgmt;
2505 unsigned char *mac, *bssid;
2506 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2507 #ifdef CONFIG_8723AU_AP_MODE
2511 int ssid_ielen_diff;
2514 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2515 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2516 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2517 unsigned int rate_len;
2519 /* DBG_8723A("%s\n", __func__); */
2521 if (cur_network->IELength > MAX_IE_SZ)
2524 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2526 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2530 /* update attribute */
2531 pattrib = &pmgntframe->attrib;
2532 update_mgntframe_attrib23a(padapter, pattrib);
2534 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2536 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
2537 mgmt = (struct ieee80211_mgmt *)pframe;
2539 mac = myid(&padapter->eeprompriv);
2540 bssid = cur_network->MacAddress;
2542 mgmt->frame_control =
2543 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
2545 ether_addr_copy(mgmt->da, da);
2546 ether_addr_copy(mgmt->sa, mac);
2547 ether_addr_copy(mgmt->bssid, bssid);
2549 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2550 pmlmeext->mgnt_seq++;
2552 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2554 /* timestamp will be inserted by hardware */
2555 put_unaligned_le16(cur_network->beacon_interval,
2556 &mgmt->u.probe_resp.beacon_int);
2558 put_unaligned_le16(cur_network->capability,
2559 &mgmt->u.probe_resp.capab_info);
2561 pframe = mgmt->u.probe_resp.variable;
2563 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
2565 /* below for ad-hoc mode */
2567 #ifdef CONFIG_8723AU_AP_MODE
2568 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2569 pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2570 WLAN_OUI_TYPE_MICROSOFT_WPS,
2572 cur_network->IELength);
2574 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2575 pframe += cur_network->IELength;
2576 pattrib->pktlen += cur_network->IELength;
2578 /* retrieve SSID IE from cur_network->Ssid */
2580 ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable,
2581 WLAN_EID_SSID, &ssid_ielen,
2582 pframe - mgmt->u.probe_resp.variable);
2584 ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
2586 if (ssid_ie && cur_network->Ssid.ssid_len) {
2587 uint remainder_ielen;
2590 remainder_ie = ssid_ie + 2;
2592 remainder_ielen = pframe - remainder_ie;
2594 DBG_8723A_LEVEL(_drv_warning_, "%s(%s): "
2595 "remainder_ielen > MAX_IE_SZ\n",
2596 __func__, padapter->pnetdev->name);
2597 if (remainder_ielen > MAX_IE_SZ)
2598 remainder_ielen = MAX_IE_SZ;
2600 memcpy(buf, remainder_ie, remainder_ielen);
2601 memcpy(remainder_ie + ssid_ielen_diff, buf,
2603 *(ssid_ie + 1) = cur_network->Ssid.ssid_len;
2604 memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
2605 cur_network->Ssid.ssid_len);
2607 pframe += ssid_ielen_diff;
2608 pattrib->pktlen += ssid_ielen_diff;
2614 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2615 cur_network->Ssid.ssid_len,
2616 cur_network->Ssid.ssid,
2619 /* supported rates... */
2620 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2621 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2622 ((rate_len > 8)? 8: rate_len),
2623 cur_network->SupportedRates,
2626 /* DS parameter set */
2627 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
2628 (unsigned char *)&cur_network->DSConfig,
2631 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
2634 /* IBSS Parameter Set... */
2635 /* ATIMWindow = cur->ATIMWindow; */
2637 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2638 (unsigned char *)&ATIMWindow,
2642 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2643 &erpinfo, &pattrib->pktlen);
2646 /* EXTERNDED SUPPORTED RATE */
2648 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2650 cur_network->SupportedRates + 8,
2653 /* todo:HT for adhoc */
2656 pattrib->last_txcmdsz = pattrib->pktlen;
2658 dump_mgntframe23a(padapter, pmgntframe);
2663 static int _issue_probereq(struct rtw_adapter *padapter,
2664 struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
2667 struct xmit_frame *pmgntframe;
2668 struct pkt_attrib *pattrib;
2669 unsigned char *pframe;
2670 struct ieee80211_hdr *pwlanhdr;
2672 unsigned char bssrate[NumRates];
2673 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2674 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2675 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2676 int bssrate_len = 0;
2677 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2679 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2682 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2686 /* update attribute */
2687 pattrib = &pmgntframe->attrib;
2688 update_mgntframe_attrib23a(padapter, pattrib);
2690 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2692 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2693 pwlanhdr = (struct ieee80211_hdr *)pframe;
2695 mac = myid(&padapter->eeprompriv);
2697 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2698 IEEE80211_STYPE_PROBE_REQ);
2701 /* unicast probe request frame */
2702 ether_addr_copy(pwlanhdr->addr1, da);
2703 ether_addr_copy(pwlanhdr->addr3, da);
2705 /* broadcast probe request frame */
2706 ether_addr_copy(pwlanhdr->addr1, bc_addr);
2707 ether_addr_copy(pwlanhdr->addr3, bc_addr);
2710 ether_addr_copy(pwlanhdr->addr2, mac);
2712 pwlanhdr->seq_ctrl =
2713 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2715 pmlmeext->mgnt_seq++;
2717 pframe += sizeof (struct ieee80211_hdr_3addr);
2718 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
2721 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
2722 pssid->ssid, &pattrib->pktlen);
2724 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
2727 get_rate_set23a(padapter, bssrate, &bssrate_len);
2729 if (bssrate_len > 8) {
2730 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
2731 bssrate, &pattrib->pktlen);
2732 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2733 (bssrate_len - 8), (bssrate + 8),
2736 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2737 bssrate_len, bssrate, &pattrib->pktlen);
2740 /* add wps_ie for wps2.0 */
2741 if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
2742 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
2743 pmlmepriv->wps_probe_req_ie_len);
2744 pframe += pmlmepriv->wps_probe_req_ie_len;
2745 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2748 pattrib->last_txcmdsz = pattrib->pktlen;
2750 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2751 "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz);
2754 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
2756 dump_mgntframe23a(padapter, pmgntframe);
2764 static inline void issue_probereq(struct rtw_adapter *padapter,
2765 struct cfg80211_ssid *pssid, u8 *da)
2767 _issue_probereq(padapter, pssid, da, false);
2770 static int issue_probereq_ex(struct rtw_adapter *padapter,
2771 struct cfg80211_ssid *pssid, u8 *da,
2772 int try_cnt, int wait_ms)
2776 unsigned long start = jiffies;
2779 ret = _issue_probereq(padapter, pssid, da,
2780 wait_ms > 0 ? true : false);
2784 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2787 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2790 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2797 if (try_cnt && wait_ms) {
2799 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
2800 __func__, padapter->pnetdev->name,
2801 da, rtw_get_oper_ch23a(padapter),
2802 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2803 jiffies_to_msecs(jiffies - start));
2805 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
2806 __func__, padapter->pnetdev->name,
2807 rtw_get_oper_ch23a(padapter),
2808 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2809 jiffies_to_msecs(jiffies - start));
2815 /* if psta == NULL, indiate we are station(client) now... */
2816 static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
2817 unsigned short status)
2819 struct xmit_frame *pmgntframe;
2820 struct pkt_attrib *pattrib;
2821 unsigned char *pframe;
2822 struct ieee80211_mgmt *mgmt;
2825 int use_shared_key = 0;
2826 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2827 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2828 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2830 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2834 /* update attribute */
2835 pattrib = &pmgntframe->attrib;
2836 update_mgntframe_attrib23a(padapter, pattrib);
2838 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2840 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2841 mgmt = (struct ieee80211_mgmt *)pframe;
2843 mgmt->frame_control =
2844 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
2845 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2846 pmlmeext->mgnt_seq++;
2848 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable);
2850 if (psta) { /* for AP mode */
2851 #ifdef CONFIG_8723AU_AP_MODE
2852 unsigned short val16;
2854 ether_addr_copy(mgmt->da, psta->hwaddr);
2855 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2856 ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv));
2858 /* setting auth algo number */
2859 val16 = (u16)psta->authalg;
2861 if (status != WLAN_STATUS_SUCCESS)
2867 mgmt->u.auth.auth_alg = cpu_to_le16(val16);
2869 /* setting auth seq number */
2870 mgmt->u.auth.auth_transaction =
2871 cpu_to_le16((u16)psta->auth_seq);
2873 /* setting status code... */
2874 mgmt->u.auth.status_code = cpu_to_le16(status);
2876 pframe = mgmt->u.auth.variable;
2877 /* added challenging text... */
2878 if ((psta->auth_seq == 2) &&
2879 (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
2880 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2881 psta->chg_txt, &pattrib->pktlen);
2884 struct ieee80211_mgmt *iv_mgmt;
2886 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
2887 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2888 ether_addr_copy(mgmt->bssid,
2889 get_my_bssid23a(&pmlmeinfo->network));
2891 /* setting auth algo number */
2892 /* 0:OPEN System, 1:Shared key */
2893 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
2895 auth_algo = WLAN_AUTH_SHARED_KEY;
2897 auth_algo = WLAN_AUTH_OPEN;
2899 /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
2900 (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
2901 pmlmeinfo->auth_seq); */
2903 /* setting IV for auth seq #3 */
2904 if ((pmlmeinfo->auth_seq == 3) &&
2905 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2906 (use_shared_key == 1)) {
2907 u32 *piv = (u32 *)&mgmt->u.auth;
2909 iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4);
2910 /* DBG_8723A("==> iv(%d), key_index(%d)\n",
2911 pmlmeinfo->iv, pmlmeinfo->key_index); */
2912 val32 = (pmlmeinfo->iv & 0x3fffffff) |
2913 (pmlmeinfo->key_index << 30);
2915 put_unaligned_le32(val32, piv);
2917 pattrib->pktlen += 4;
2919 pattrib->iv_len = IEEE80211_WEP_IV_LEN;
2923 iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo);
2925 /* setting auth seq number */
2926 iv_mgmt->u.auth.auth_transaction =
2927 cpu_to_le16(pmlmeinfo->auth_seq);
2929 /* setting status code... */
2930 iv_mgmt->u.auth.status_code = cpu_to_le16(status);
2932 pframe = iv_mgmt->u.auth.variable;
2934 /* then checking to see if sending challenging text... */
2935 if ((pmlmeinfo->auth_seq == 3) &&
2936 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2937 (use_shared_key == 1)) {
2938 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2942 mgmt->frame_control |=
2943 cpu_to_le16(IEEE80211_FCTL_PROTECTED);
2945 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2947 pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40;
2949 pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
2951 pattrib->pktlen += pattrib->icv_len;
2955 pattrib->last_txcmdsz = pattrib->pktlen;
2957 rtw_wep_encrypt23a(padapter, pmgntframe);
2958 DBG_8723A("%s\n", __func__);
2959 dump_mgntframe23a(padapter, pmgntframe);
2964 #ifdef CONFIG_8723AU_AP_MODE
2965 static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
2966 struct sta_info *pstat, u16 pkt_type)
2968 struct xmit_frame *pmgntframe;
2969 struct ieee80211_mgmt *mgmt;
2970 struct pkt_attrib *pattrib;
2971 unsigned char *pframe;
2972 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2973 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2974 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2975 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2976 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
2978 u8 *ie = pnetwork->IEs;
2980 DBG_8723A("%s\n", __func__);
2982 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2986 /* update attribute */
2987 pattrib = &pmgntframe->attrib;
2988 update_mgntframe_attrib23a(padapter, pattrib);
2990 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2992 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2993 mgmt = (struct ieee80211_mgmt *)pframe;
2995 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
2997 ether_addr_copy(mgmt->da, pstat->hwaddr);
2998 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2999 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3001 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3003 pmlmeext->mgnt_seq++;
3005 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3007 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
3009 mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability);
3010 mgmt->u.assoc_resp.status_code = cpu_to_le16(status);
3011 mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
3013 pframe = mgmt->u.assoc_resp.variable;
3015 if (pstat->bssratelen <= 8) {
3016 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3017 pstat->bssratelen, pstat->bssrateset,
3020 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3021 pstat->bssrateset, &pattrib->pktlen);
3022 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3023 pstat->bssratelen - 8,
3024 pstat->bssrateset + 8, &pattrib->pktlen);
3027 if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
3028 /* FILL HT CAP INFO IE */
3029 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
3030 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie,
3031 pnetwork->IELength);
3033 memcpy(pframe, p, p[1] + 2);
3034 pframe += (p[1] + 2);
3035 pattrib->pktlen += (p[1] + 2);
3038 /* FILL HT ADD INFO IE */
3039 /* p = hostapd_eid_ht_operation(hapd, p); */
3040 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie,
3041 pnetwork->IELength);
3042 if (p && p[1] > 0) {
3043 memcpy(pframe, p, p[1] + 2);
3044 pframe += (p[1] + 2);
3045 pattrib->pktlen += (p[1] + 2);
3050 if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) {
3051 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
3055 for (p = ie; ; p += (ie_len + 2)) {
3056 p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
3057 pnetwork->IELength - (ie_len + 2));
3062 if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) {
3063 memcpy(pframe, p, ie_len + 2);
3064 pframe += (ie_len + 2);
3065 pattrib->pktlen += (ie_len + 2);
3070 if (!p || ie_len == 0)
3075 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
3076 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3077 REALTEK_96B_IE, &pattrib->pktlen);
3080 pattrib->last_txcmdsz = pattrib->pktlen;
3082 dump_mgntframe23a(padapter, pmgntframe);
3086 static void issue_assocreq(struct rtw_adapter *padapter)
3089 struct xmit_frame *pmgntframe;
3090 struct pkt_attrib *pattrib;
3091 unsigned char *pframe;
3093 struct ieee80211_mgmt *mgmt;
3094 unsigned int i, j, index = 0;
3095 unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
3096 struct registry_priv *pregpriv = &padapter->registrypriv;
3097 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3098 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3099 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3100 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3101 int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
3104 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3108 /* update attribute */
3109 pattrib = &pmgntframe->attrib;
3110 update_mgntframe_attrib23a(padapter, pattrib);
3112 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3114 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
3115 mgmt = (struct ieee80211_mgmt *)pframe;
3117 mgmt->frame_control =
3118 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ);
3120 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
3121 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3122 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3124 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3125 pmlmeext->mgnt_seq++;
3128 put_unaligned_le16(pmlmeinfo->network.capability,
3129 &mgmt->u.assoc_req.capab_info);
3130 /* todo: listen interval for power saving */
3131 put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval);
3133 pframe = mgmt->u.assoc_req.variable;
3134 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
3137 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
3138 pmlmeinfo->network.Ssid.ssid_len,
3139 pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
3141 /* supported rate & extended supported rate */
3143 get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
3144 /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */
3146 /* for JAPAN, channel 14 can only uses B Mode(CCK) */
3147 if (pmlmeext->cur_channel == 14)
3148 sta_bssrate_len = 4;
3150 /* for (i = 0; i < sta_bssrate_len; i++) { */
3151 /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
3154 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3155 if (pmlmeinfo->network.SupportedRates[i] == 0)
3157 DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
3158 pmlmeinfo->network.SupportedRates[i]);
3161 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3162 if (pmlmeinfo->network.SupportedRates[i] == 0)
3165 /* Check if the AP's supported rates are also
3166 supported by STA. */
3167 for (j = 0; j < sta_bssrate_len; j++) {
3168 /* Avoid the proprietary data rate (22Mbps) of
3169 Handlink WSG-4000 AP */
3170 if ((pmlmeinfo->network.SupportedRates[i] |
3171 IEEE80211_BASIC_RATE_MASK) ==
3172 (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
3173 /* DBG_8723A("match i = %d, j =%d\n", i, j); */
3178 if (j == sta_bssrate_len) {
3179 /* the rate is not supported by STA */
3180 DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
3181 "STA!\n", __func__, i,
3182 pmlmeinfo->network.SupportedRates[i]);
3184 /* the rate is supported by STA */
3185 bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
3189 bssrate_len = index;
3190 DBG_8723A("bssrate_len = %d\n", bssrate_len);
3192 if (bssrate_len == 0) {
3193 rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
3194 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
3195 goto exit; /* don't connect to AP if no joint supported rate */
3198 if (bssrate_len > 8) {
3199 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3200 bssrate, &pattrib->pktlen);
3201 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3202 (bssrate_len - 8), (bssrate + 8),
3205 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3206 bssrate_len, bssrate, &pattrib->pktlen);
3210 pie = pmlmeinfo->network.IEs;
3211 pie_len = pmlmeinfo->network.IELength;
3213 p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
3215 pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
3219 if (padapter->mlmepriv.htpriv.ht_option) {
3220 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
3222 if (p && !is_ap_in_tkip23a(padapter)) {
3223 struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap;
3225 memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap));
3227 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
3228 if (pregpriv->cbw40_enable == 0) {
3229 cap->cap_info &= ~cpu_to_le16(
3230 IEEE80211_HT_CAP_SGI_40 |
3231 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3233 cap->cap_info |= cpu_to_le16(
3234 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3237 /* todo: disable SM power save mode */
3238 cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
3240 rf_type = rtl8723a_get_rf_type(padapter);
3241 /* switch (pregpriv->rf_config) */
3244 /* RX STBC One spatial stream */
3245 if (pregpriv->rx_stbc)
3246 cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3248 memcpy(&cap->mcs, MCS_rate_1R23A, 16);
3254 /* enable for 2.4/5 GHz */
3255 if (pregpriv->rx_stbc == 0x3 ||
3256 (pmlmeext->cur_wireless_mode &
3258 /* enable for 2.4GHz */
3259 pregpriv->rx_stbc == 0x1) ||
3260 (pmlmeext->cur_wireless_mode &
3262 pregpriv->rx_stbc == 0x2) ||
3263 /* enable for 5GHz */
3264 pregpriv->wifi_spec == 1) {
3265 DBG_8723A("declare supporting RX "
3267 /* RX STBC two spatial stream */
3268 cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3270 memcpy(&cap->mcs, MCS_rate_2R23A, 16);
3274 if (rtl8723a_BT_coexist(padapter) &&
3275 rtl8723a_BT_using_antenna_1(padapter)) {
3277 cap->ampdu_params_info &=
3278 ~IEEE80211_HT_AMPDU_PARM_FACTOR;
3279 /* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */
3282 pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
3283 p[1], (u8 *)&pmlmeinfo->ht_cap,
3288 /* vendor specific IE, such as WPA, WMM, WPS */
3289 for (i = 0; i < pmlmeinfo->network.IELength;) {
3290 p = pmlmeinfo->network.IEs + i;
3293 case WLAN_EID_VENDOR_SPECIFIC:
3294 if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) ||
3295 !memcmp(p + 2, WMM_OUI23A, 4) ||
3296 !memcmp(p + 2, WPS_OUI23A, 4)) {
3299 if (!padapter->registrypriv.wifi_spec) {
3300 /* Commented by Kurt 20110629 */
3301 /* In some older APs, WPS handshake */
3302 /* would be fail if we append vender
3303 extensions informations to AP */
3304 if (!memcmp(p + 2, WPS_OUI23A, 4))
3307 pframe = rtw_set_ie23a(pframe,
3308 WLAN_EID_VENDOR_SPECIFIC,
3321 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3322 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3323 REALTEK_96B_IE, &pattrib->pktlen);
3325 pattrib->last_txcmdsz = pattrib->pktlen;
3326 dump_mgntframe23a(padapter, pmgntframe);
3331 pmlmepriv->assoc_req_len = 0;
3332 if (ret == _SUCCESS) {
3333 kfree(pmlmepriv->assoc_req);
3334 pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
3335 if (pmlmepriv->assoc_req) {
3336 memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen);
3337 pmlmepriv->assoc_req_len = pattrib->pktlen;
3340 kfree(pmlmepriv->assoc_req);
3345 /* when wait_ack is true, this function should be called at process context */
3346 static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3347 unsigned int power_mode, int wait_ack)
3350 struct xmit_frame *pmgntframe;
3351 struct pkt_attrib *pattrib;
3352 unsigned char *pframe;
3353 struct ieee80211_hdr *pwlanhdr;
3354 struct xmit_priv *pxmitpriv;
3355 struct mlme_ext_priv *pmlmeext;
3356 struct mlme_ext_info *pmlmeinfo;
3358 /* DBG_8723A("%s:%d\n", __func__, power_mode); */
3363 pxmitpriv = &padapter->xmitpriv;
3364 pmlmeext = &padapter->mlmeextpriv;
3365 pmlmeinfo = &pmlmeext->mlmext_info;
3367 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3371 /* update attribute */
3372 pattrib = &pmgntframe->attrib;
3373 update_mgntframe_attrib23a(padapter, pattrib);
3374 pattrib->retry_ctrl = false;
3376 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3378 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3379 pwlanhdr = (struct ieee80211_hdr *)pframe;
3381 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3382 IEEE80211_STYPE_NULLFUNC);
3384 if ((pmlmeinfo->state&0x03) == MSR_AP)
3385 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3386 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3387 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3390 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
3392 ether_addr_copy(pwlanhdr->addr1, da);
3393 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3394 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3396 pwlanhdr->seq_ctrl =
3397 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3398 pmlmeext->mgnt_seq++;
3400 pframe += sizeof(struct ieee80211_hdr_3addr);
3401 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3403 pattrib->last_txcmdsz = pattrib->pktlen;
3406 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3408 dump_mgntframe23a(padapter, pmgntframe);
3416 /* when wait_ms >0 , this function should be called at process context */
3417 /* da == NULL for station mode */
3418 int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3419 unsigned int power_mode, int try_cnt, int wait_ms)
3423 unsigned long start = jiffies;
3424 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3425 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3427 /* da == NULL, assume it's null data for sta to ap*/
3429 da = get_my_bssid23a(&pmlmeinfo->network);
3432 ret = _issue_nulldata23a(padapter, da, power_mode,
3433 wait_ms > 0 ? true : false);
3437 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3440 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3443 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3450 if (try_cnt && wait_ms) {
3452 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3453 __func__, padapter->pnetdev->name,
3454 da, rtw_get_oper_ch23a(padapter),
3455 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3456 jiffies_to_msecs(jiffies - start));
3458 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3459 __func__, padapter->pnetdev->name,
3460 rtw_get_oper_ch23a(padapter),
3461 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3462 jiffies_to_msecs(jiffies - start));
3468 /* when wait_ack is true, this function should be called at process context */
3469 static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
3470 unsigned char *da, u16 tid, int wait_ack)
3473 struct xmit_frame *pmgntframe;
3474 struct pkt_attrib *pattrib;
3475 unsigned char *pframe;
3476 struct ieee80211_qos_hdr *pwlanhdr;
3477 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3478 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3479 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3481 DBG_8723A("%s\n", __func__);
3483 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3487 /* update attribute */
3488 pattrib = &pmgntframe->attrib;
3489 update_mgntframe_attrib23a(padapter, pattrib);
3491 pattrib->hdrlen += 2;
3492 pattrib->qos_en = true;
3494 pattrib->ack_policy = 0;
3497 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3499 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3500 pwlanhdr = (struct ieee80211_qos_hdr *)pframe;
3502 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3503 IEEE80211_STYPE_QOS_NULLFUNC);
3505 if ((pmlmeinfo->state&0x03) == MSR_AP)
3506 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3507 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3508 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3511 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
3513 pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK);
3514 pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) &
3515 IEEE80211_QOS_CTL_ACK_POLICY_MASK);
3517 pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
3519 ether_addr_copy(pwlanhdr->addr1, da);
3520 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3521 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3523 pwlanhdr->seq_ctrl =
3524 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3525 pmlmeext->mgnt_seq++;
3527 pframe += sizeof(struct ieee80211_qos_hdr);
3528 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3530 pattrib->last_txcmdsz = pattrib->pktlen;
3533 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3535 dump_mgntframe23a(padapter, pmgntframe);
3543 /* when wait_ms >0 , this function should be called at process context */
3544 /* da == NULL for station mode */
3545 int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3546 u16 tid, int try_cnt, int wait_ms)
3550 unsigned long start = jiffies;
3551 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3552 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3554 /* da == NULL, assume it's null data for sta to ap*/
3556 da = get_my_bssid23a(&pmlmeinfo->network);
3559 ret = _issue_qos_nulldata23a(padapter, da, tid,
3560 wait_ms > 0 ? true : false);
3564 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3567 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3569 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3576 if (try_cnt && wait_ms) {
3578 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3579 __func__, padapter->pnetdev->name,
3580 da, rtw_get_oper_ch23a(padapter),
3581 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3582 jiffies_to_msecs(jiffies - start));
3584 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3585 __func__, padapter->pnetdev->name,
3586 rtw_get_oper_ch23a(padapter),
3587 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3588 jiffies_to_msecs(jiffies - start));
3594 static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da,
3595 unsigned short reason, u8 wait_ack)
3597 struct xmit_frame *pmgntframe;
3598 struct pkt_attrib *pattrib;
3599 struct ieee80211_mgmt *mgmt;
3600 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3601 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3602 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3605 /* DBG_8723A("%s to %pM\n", __func__, da); */
3607 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3611 /* update attribute */
3612 pattrib = &pmgntframe->attrib;
3613 update_mgntframe_attrib23a(padapter, pattrib);
3614 pattrib->retry_ctrl = false;
3616 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3618 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3620 mgmt->frame_control =
3621 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
3623 ether_addr_copy(mgmt->da, da);
3624 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3625 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3627 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3628 pmlmeext->mgnt_seq++;
3630 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2;
3632 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
3634 pattrib->last_txcmdsz = pattrib->pktlen;
3637 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3639 dump_mgntframe23a(padapter, pmgntframe);
3647 int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
3648 unsigned short reason)
3650 DBG_8723A("%s to %pM\n", __func__, da);
3651 return _issue_deauth(padapter, da, reason, false);
3654 static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
3655 unsigned short reason, int try_cnt, int wait_ms)
3659 unsigned long start = jiffies;
3662 ret = _issue_deauth(padapter, da, reason,
3663 wait_ms >0 ? true : false);
3667 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3670 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3673 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3680 if (try_cnt && wait_ms) {
3682 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3683 __func__, padapter->pnetdev->name,
3684 da, rtw_get_oper_ch23a(padapter),
3685 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3686 jiffies_to_msecs(jiffies - start));
3688 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3689 __func__, padapter->pnetdev->name,
3690 rtw_get_oper_ch23a(padapter),
3691 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3692 jiffies_to_msecs(jiffies - start));
3698 void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
3699 u8 *ra, u8 new_ch, u8 ch_offset)
3701 struct xmit_frame *pmgntframe;
3702 struct pkt_attrib *pattrib;
3703 unsigned char *pframe;
3704 struct ieee80211_mgmt *mgmt;
3705 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3706 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3708 DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n",
3709 __func__, padapter->pnetdev->name, ra, new_ch, ch_offset);
3711 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3715 /* update attribute */
3716 pattrib = &pmgntframe->attrib;
3717 update_mgntframe_attrib23a(padapter, pattrib);
3719 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3721 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3723 mgmt->frame_control =
3724 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3726 ether_addr_copy(mgmt->da, ra); /* RA */
3727 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */
3728 ether_addr_copy(mgmt->bssid, ra); /* DA = RA */
3730 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3731 pmlmeext->mgnt_seq++;
3733 mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
3734 mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
3736 pframe = mgmt->u.action.u.chan_switch.variable;
3737 pattrib->pktlen = offsetof(struct ieee80211_mgmt,
3738 u.action.u.chan_switch.variable);
3740 pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
3742 pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
3743 hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
3745 pattrib->last_txcmdsz = pattrib->pktlen;
3747 dump_mgntframe23a(padapter, pmgntframe);
3750 void issue_action_BA23a(struct rtw_adapter *padapter,
3751 const unsigned char *raddr,
3752 unsigned char action, unsigned short status)
3756 u16 BA_starting_seqctrl;
3758 int max_rx_ampdu_factor;
3759 struct xmit_frame *pmgntframe;
3760 struct pkt_attrib *pattrib;
3761 struct ieee80211_mgmt *mgmt;
3762 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3763 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3764 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3765 struct sta_info *psta;
3766 struct sta_priv *pstapriv = &padapter->stapriv;
3767 struct registry_priv *pregpriv = &padapter->registrypriv;
3768 u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
3770 DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status);
3772 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3776 /* update attribute */
3777 pattrib = &pmgntframe->attrib;
3778 update_mgntframe_attrib23a(padapter, pattrib);
3780 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3782 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3784 mgmt->frame_control =
3785 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3787 ether_addr_copy(mgmt->da, raddr);
3788 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3789 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3791 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3792 pmlmeext->mgnt_seq++;
3794 mgmt->u.action.category = WLAN_CATEGORY_BACK;
3796 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1;
3799 case WLAN_ACTION_ADDBA_REQ:
3800 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req);
3802 mgmt->u.action.u.addba_req.action_code = action;
3805 pmlmeinfo->dialogToken++;
3806 } while (pmlmeinfo->dialogToken == 0);
3808 mgmt->u.action.u.addba_req.dialog_token =
3809 pmlmeinfo->dialogToken;
3811 if (rtl8723a_BT_coexist(padapter) &&
3812 rtl8723a_BT_using_antenna_1(padapter) &&
3813 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3814 memcmp(raddr, tendaAPMac, 3))) {
3815 /* A-MSDU NOT Supported */
3817 /* immediate Block Ack */
3818 BA_para_set |= (1 << 1) &
3819 IEEE80211_ADDBA_PARAM_POLICY_MASK;
3821 BA_para_set |= (status << 2) &
3822 IEEE80211_ADDBA_PARAM_TID_MASK;
3823 /* max buffer size is 8 MSDU */
3824 BA_para_set |= (8 << 6) &
3825 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3827 /* immediate ack & 64 buffer size */
3828 BA_para_set = 0x1002 | ((status & 0xf) << 2);
3831 put_unaligned_le16(BA_para_set,
3832 &mgmt->u.action.u.addba_req.capab);
3835 put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout);
3837 psta = rtw_get_stainfo23a(pstapriv, raddr);
3841 idx = status & 0x07;
3843 (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1;
3845 DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
3848 psta->BA_starting_seqctrl[idx] = start_seq;
3850 BA_starting_seqctrl = start_seq << 4;
3852 BA_starting_seqctrl = 0;
3854 put_unaligned_le16(BA_starting_seqctrl,
3855 &mgmt->u.action.u.addba_req.start_seq_num);
3859 case WLAN_ACTION_ADDBA_RESP:
3860 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp);
3862 mgmt->u.action.u.addba_resp.action_code = action;
3863 mgmt->u.action.u.addba_resp.dialog_token =
3864 pmlmeinfo->ADDBA_req.dialog_token;
3865 put_unaligned_le16(status,
3866 &mgmt->u.action.u.addba_resp.status);
3868 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
3869 &max_rx_ampdu_factor);
3871 BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
3872 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
3873 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
3874 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
3875 BA_para_set = BA_para | 0x0800; /* 32 buffer size */
3876 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
3877 BA_para_set = BA_para | 0x0400; /* 16 buffer size */
3878 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
3879 BA_para_set = BA_para | 0x0200; /* 8 buffer size */
3881 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
3883 if (rtl8723a_BT_coexist(padapter) &&
3884 rtl8723a_BT_using_antenna_1(padapter) &&
3885 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3886 memcmp(raddr, tendaAPMac, 3))) {
3887 /* max buffer size is 8 MSDU */
3888 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3889 BA_para_set |= (8 << 6) &
3890 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3893 if (pregpriv->ampdu_amsdu == 0)/* disabled */
3894 BA_para_set &= ~BIT(0);
3895 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
3896 BA_para_set |= BIT(0);
3898 put_unaligned_le16(BA_para_set,
3899 &mgmt->u.action.u.addba_resp.capab);
3901 mgmt->u.action.u.addba_resp.timeout
3902 = pmlmeinfo->ADDBA_req.BA_timeout_value;
3904 pattrib->pktlen += 8;
3906 case WLAN_ACTION_DELBA:
3907 pattrib->pktlen += sizeof(mgmt->u.action.u.delba);
3909 mgmt->u.action.u.delba.action_code = action;
3910 BA_para_set = (status & 0x1F) << 3;
3911 mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set);
3912 mgmt->u.action.u.delba.reason_code =
3913 cpu_to_le16(WLAN_REASON_QSTA_NOT_USE);
3915 pattrib->pktlen += 5;
3921 pattrib->last_txcmdsz = pattrib->pktlen;
3923 dump_mgntframe23a(padapter, pmgntframe);
3926 int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
3928 struct sta_priv *pstapriv = &padapter->stapriv;
3929 struct sta_info *psta = NULL;
3930 /* struct recv_reorder_ctrl *preorder_ctrl; */
3931 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3932 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3935 if ((pmlmeinfo->state&0x03) != MSR_AP)
3936 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3939 psta = rtw_get_stainfo23a(pstapriv, addr);
3943 if (initiator == 0) { /* recipient */
3944 for (tid = 0; tid < MAXTID; tid++) {
3945 if (psta->recvreorder_ctrl[tid].enable == true) {
3946 DBG_8723A("rx agg disable tid(%d)\n", tid);
3947 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3948 psta->recvreorder_ctrl[tid].enable = false;
3949 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
3952 } else if (initiator == 1) { /* originator */
3953 for (tid = 0; tid < MAXTID; tid++) {
3954 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
3955 DBG_8723A("tx agg disable tid(%d)\n", tid);
3956 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3957 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3958 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3966 int send_beacon23a(struct rtw_adapter *padapter)
3971 unsigned long start = jiffies;
3972 unsigned int passing_time;
3974 rtl8723a_bcn_valid(padapter);
3976 issue_beacon23a(padapter, 100);
3980 bxmitok = rtl8723a_get_bcn_valid(padapter);
3982 } while ((poll % 10) != 0 && !bxmitok &&
3983 !padapter->bSurpriseRemoved &&
3984 !padapter->bDriverStopped);
3986 } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
3987 !padapter->bDriverStopped);
3989 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
3992 passing_time = jiffies_to_msecs(jiffies - start);
3995 DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
3999 if (passing_time > 100 || issue > 3)
4000 DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
4001 __func__, issue, poll, passing_time);
4006 /****************************************************************************
4008 Following are some utitity functions for WiFi MLME
4010 *****************************************************************************/
4012 bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
4016 u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
4017 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
4018 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
4019 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
4021 for (i = 0; i < sizeof(Channel_5G); i++)
4022 if (channel == Channel_5G[i])
4027 static void rtw_site_survey(struct rtw_adapter *padapter)
4029 unsigned char survey_channel = 0;
4030 enum rt_scan_type ScanType = SCAN_PASSIVE;
4031 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4032 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4033 struct rtw_ieee80211_channel *ch;
4035 if (pmlmeext->sitesurvey_res.channel_idx <
4036 pmlmeext->sitesurvey_res.ch_num) {
4037 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
4038 survey_channel = ch->hw_value;
4039 ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ?
4040 SCAN_PASSIVE : SCAN_ACTIVE;
4043 if (survey_channel != 0) {
4044 /* PAUSE 4-AC Queue when site_survey */
4045 if (pmlmeext->sitesurvey_res.channel_idx == 0)
4046 set_channel_bwmode23a(padapter, survey_channel,
4047 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
4048 HT_CHANNEL_WIDTH_20);
4050 SelectChannel23a(padapter, survey_channel);
4052 if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
4056 for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
4057 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
4058 /* todo: to issue two probe req??? */
4059 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4060 /* msleep(SURVEY_TO>>1); */
4061 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4065 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4066 /* todo: to issue two probe req??? */
4067 issue_probereq(padapter, NULL, NULL);
4068 /* msleep(SURVEY_TO>>1); */
4069 issue_probereq(padapter, NULL, NULL);
4073 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
4075 /* channel number is 0 or this channel is not valid. */
4076 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
4078 /* switch back to the original channel */
4080 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
4081 pmlmeext->cur_ch_offset,
4082 pmlmeext->cur_bwmode);
4084 /* flush 4-AC Queue after rtw_site_survey */
4088 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4090 /* restore RX GAIN */
4091 rtl8723a_set_initial_gain(padapter, 0xff);
4092 /* turn on dynamic functions */
4093 rtl8723a_odm_support_ability_restore(padapter);
4095 if (is_client_associated_to_ap23a(padapter) == true)
4096 issue_nulldata23a(padapter, NULL, 0, 3, 500);
4098 rtl8723a_mlme_sitesurvey(padapter, 0);
4100 report_surveydone_event23a(padapter);
4102 pmlmeext->chan_scan_time = SURVEY_TO;
4103 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
4109 /* collect bss info from Beacon and Probe request/response frames. */
4110 static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
4111 struct recv_frame *precv_frame)
4113 struct sk_buff *skb = precv_frame->pkt;
4114 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
4115 struct registry_priv *pregistrypriv = &padapter->registrypriv;
4116 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4117 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4118 struct wlan_bssid_ex *bssid;
4121 unsigned int length;
4126 bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
4130 if (ieee80211_is_beacon(mgmt->frame_control)) {
4131 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4132 pie = mgmt->u.beacon.variable;
4133 bssid->reserved = 1;
4135 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4136 bssid->beacon_interval =
4137 get_unaligned_le16(&mgmt->u.beacon.beacon_int);
4138 bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
4139 } else if (ieee80211_is_probe_req(mgmt->frame_control)) {
4140 length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
4141 pie = mgmt->u.probe_req.variable;
4142 bssid->reserved = 2;
4143 bssid->capability = 0;
4144 bssid->beacon_interval =
4145 padapter->registrypriv.dev_network.beacon_interval;
4147 } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
4149 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
4150 pie = mgmt->u.probe_resp.variable;
4151 bssid->reserved = 3;
4153 get_unaligned_le16(&mgmt->u.probe_resp.capab_info);
4154 bssid->beacon_interval =
4155 get_unaligned_le16(&mgmt->u.probe_resp.beacon_int);
4156 bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp);
4158 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4159 pie = mgmt->u.beacon.variable;
4160 bssid->reserved = 0;
4162 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4163 bssid->beacon_interval =
4164 padapter->registrypriv.dev_network.beacon_interval;
4168 if (length > MAX_IE_SZ) {
4169 /* DBG_8723A("IE too long for survey event\n"); */
4174 bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
4176 /* below is to copy the information element */
4177 bssid->IELength = length;
4178 memcpy(bssid->IEs, pie, bssid->IELength);
4180 /* get the signal strength */
4181 /* in dBM.raw data */
4182 bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
4183 bssid->SignalQuality =
4184 precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
4185 bssid->SignalStrength =
4186 precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
4189 p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength);
4192 DBG_8723A("marc: cannot find SSID for survey event\n");
4196 if (p[1] > IEEE80211_MAX_SSID_LEN) {
4197 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4198 "event\n", __func__, __LINE__, p[1]);
4201 memcpy(bssid->Ssid.ssid, p + 2, p[1]);
4202 bssid->Ssid.ssid_len = p[1];
4204 /* checking rate info... */
4206 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength);
4208 if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
4209 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4210 "event\n", __func__, __LINE__, p[1]);
4213 memcpy(bssid->SupportedRates, p + 2, p[1]);
4217 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs,
4220 if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
4221 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4222 "event\n", __func__, __LINE__, p[1]);
4225 memcpy(bssid->SupportedRates + i, p + 2, p[1]);
4228 /* Checking for DSConfig */
4229 p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength);
4231 bssid->DSConfig = 0;
4234 bssid->DSConfig = p[2];
4235 } else {/* In 5G, some ap do not have DSSET IE */
4236 /* checking HT info for channel */
4237 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs,
4240 struct ieee80211_ht_operation *HT_info =
4241 (struct ieee80211_ht_operation *)(p + 2);
4242 bssid->DSConfig = HT_info->primary_chan;
4243 } else /* use current channel */
4244 bssid->DSConfig = rtw_get_oper_ch23a(padapter);
4247 if (ieee80211_is_probe_req(mgmt->frame_control)) {
4249 bssid->ifmode = NL80211_IFTYPE_STATION;
4250 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4255 if (bssid->capability & WLAN_CAPABILITY_ESS) {
4256 bssid->ifmode = NL80211_IFTYPE_STATION;
4257 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4259 bssid->ifmode = NL80211_IFTYPE_ADHOC;
4260 ether_addr_copy(bssid->MacAddress, mgmt->bssid);
4263 if (bssid->capability & WLAN_CAPABILITY_PRIVACY)
4268 bssid->ATIMWindow = 0;
4270 /* 20/40 BSS Coexistence check */
4271 if (pregistrypriv->wifi_spec == 1 &&
4272 pmlmeinfo->bwmode_updated == false) {
4273 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4275 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs,
4277 if (p && p[1] > 0) {
4278 struct ieee80211_ht_cap *pHT_caps;
4280 pHT_caps = (struct ieee80211_ht_cap *)(p + 2);
4282 if (pHT_caps->cap_info &
4283 cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT))
4284 pmlmepriv->num_FortyMHzIntolerant++;
4286 pmlmepriv->num_sta_no_ht++;
4290 /* mark bss info receiving from nearby channel as SignalQuality 101 */
4291 if (bssid->DSConfig != rtw_get_oper_ch23a(padapter))
4292 bssid->SignalQuality = 101;
4300 static void start_create_ibss(struct rtw_adapter *padapter)
4302 unsigned short caps;
4303 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4304 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4305 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4307 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4308 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4310 /* update wireless mode */
4311 update_wireless_mode23a(padapter);
4313 /* update capability */
4314 caps = pnetwork->capability;
4315 update_capinfo23a(padapter, caps);
4316 if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */
4317 rtl8723a_set_sec_cfg(padapter, 0xcf);
4319 /* switch channel */
4320 /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4321 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
4323 rtl8723a_SetBeaconRelatedRegisters(padapter);
4325 /* set msr to MSR_ADHOC */
4326 pmlmeinfo->state = MSR_ADHOC;
4327 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4330 if (send_beacon23a(padapter) == _FAIL) {
4331 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
4332 "issuing beacon frame fail....\n");
4334 report_join_res23a(padapter, -1);
4335 pmlmeinfo->state = MSR_NOLINK;
4337 hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
4338 hw_var_set_mlme_join(padapter, 0);
4340 report_join_res23a(padapter, 1);
4341 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4344 DBG_8723A("%s: invalid cap:%x\n", __func__, caps);
4349 static void start_clnt_join(struct rtw_adapter *padapter)
4351 unsigned short caps;
4353 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4354 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4355 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4358 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4359 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4361 /* update wireless mode */
4362 update_wireless_mode23a(padapter);
4364 /* update capability */
4365 caps = pnetwork->capability;
4366 update_capinfo23a(padapter, caps);
4367 if (caps & WLAN_CAPABILITY_ESS) {
4368 /* switch channel */
4369 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4371 rtl8723a_set_media_status(padapter, MSR_INFRA);
4373 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
4376 rtl8723a_set_sec_cfg(padapter, val8);
4378 /* switch channel */
4379 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
4381 /* here wait for receiving the beacon to start auth */
4382 /* and enable a timer */
4383 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
4384 set_link_timer(pmlmeext, beacon_timeout);
4385 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
4386 msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
4387 pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA;
4388 } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */
4389 rtl8723a_set_media_status(padapter, MSR_ADHOC);
4391 rtl8723a_set_sec_cfg(padapter, 0xcf);
4393 /* switch channel */
4394 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4396 rtl8723a_SetBeaconRelatedRegisters(padapter);
4398 pmlmeinfo->state = MSR_ADHOC;
4400 report_join_res23a(padapter, 1);
4402 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
4407 static void start_clnt_auth(struct rtw_adapter *padapter)
4409 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4410 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4412 del_timer_sync(&pmlmeext->link_timer);
4414 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4415 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4417 pmlmeinfo->auth_seq = 1;
4418 pmlmeinfo->reauth_count = 0;
4419 pmlmeinfo->reassoc_count = 0;
4420 pmlmeinfo->link_count = 0;
4421 pmlmeext->retry = 0;
4423 /* Because of AP's not receiving deauth before */
4424 /* AP may: 1)not response auth or 2)deauth us after link is complete */
4425 /* issue deauth before issuing auth to deal with the situation */
4426 /* Commented by Albert 2012/07/21 */
4427 /* For the Win8 P2P connection, it will be hard to have a
4428 successful connection if this Wi-Fi doesn't connect to it. */
4429 issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress,
4430 WLAN_REASON_DEAUTH_LEAVING);
4432 DBG_8723A_LEVEL(_drv_always_, "start auth\n");
4433 issue_auth(padapter, NULL, 0);
4435 set_link_timer(pmlmeext, REAUTH_TO);
4438 static void start_clnt_assoc(struct rtw_adapter *padapter)
4440 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4441 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4443 del_timer_sync(&pmlmeext->link_timer);
4445 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4446 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4448 issue_assocreq(padapter);
4450 set_link_timer(pmlmeext, REASSOC_TO);
4453 int receive_disconnect23a(struct rtw_adapter *padapter,
4454 unsigned char *MacAddr, unsigned short reason)
4456 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4457 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4460 if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
4463 DBG_8723A("%s\n", __func__);
4465 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
4466 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4467 pmlmeinfo->state = MSR_NOLINK;
4468 report_del_sta_event23a(padapter, MacAddr, reason);
4470 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4471 pmlmeinfo->state = MSR_NOLINK;
4472 report_join_res23a(padapter, -2);
4479 static void process_80211d(struct rtw_adapter *padapter,
4480 struct wlan_bssid_ex *bssid)
4482 struct registry_priv *pregistrypriv;
4483 struct mlme_ext_priv *pmlmeext;
4484 struct rt_channel_info *chplan_new;
4488 pregistrypriv = &padapter->registrypriv;
4489 pmlmeext = &padapter->mlmeextpriv;
4491 /* Adjust channel plan by AP Country IE */
4492 if (pregistrypriv->enable80211d &&
4493 !pmlmeext->update_channel_plan_by_ap_done) {
4495 struct rt_channel_plan chplan_ap;
4496 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4498 u8 fcn; /* first channel number */
4499 u8 noc; /* number of channel */
4502 ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs,
4504 if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
4511 memcpy(country, p, 3);
4515 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4516 "%s: 802.11d country =%s\n", __func__, country);
4519 while ((ie - p) >= 3) {
4524 for (j = 0; j < noc; j++) {
4526 channel = fcn + j; /* 2.4 GHz */
4528 channel = fcn + j * 4; /* 5 GHz */
4530 chplan_ap.Channel[i++] = channel;
4535 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4536 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4537 chplan_new = pmlmeext->channel_set;
4540 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4542 if (i == MAX_CHANNEL_NUM ||
4543 chplan_sta[i].ChannelNum == 0 ||
4544 chplan_sta[i].ChannelNum > 14)
4547 if (j == chplan_ap.Len ||
4548 chplan_ap.Channel[j] > 14)
4551 if (chplan_sta[i].ChannelNum ==
4552 chplan_ap.Channel[j]) {
4553 chplan_new[k].ChannelNum =
4554 chplan_ap.Channel[j];
4555 chplan_new[k].ScanType = SCAN_ACTIVE;
4559 } else if (chplan_sta[i].ChannelNum <
4560 chplan_ap.Channel[j]) {
4561 chplan_new[k].ChannelNum =
4562 chplan_sta[i].ChannelNum;
4563 chplan_new[k].ScanType =
4567 } else if (chplan_sta[i].ChannelNum >
4568 chplan_ap.Channel[j]) {
4569 chplan_new[k].ChannelNum =
4570 chplan_ap.Channel[j];
4571 chplan_new[k].ScanType =
4578 /* change AP not support channel to Passive scan */
4579 while (i < MAX_CHANNEL_NUM &&
4580 chplan_sta[i].ChannelNum != 0 &&
4581 chplan_sta[i].ChannelNum <= 14) {
4582 chplan_new[k].ChannelNum =
4583 chplan_sta[i].ChannelNum;
4584 chplan_new[k].ScanType = SCAN_PASSIVE;
4589 /* add channel AP supported */
4590 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
4591 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4592 chplan_new[k].ScanType = SCAN_ACTIVE;
4597 /* keep original STA 2.4G channel plan */
4598 while (i < MAX_CHANNEL_NUM &&
4599 chplan_sta[i].ChannelNum != 0 &&
4600 chplan_sta[i].ChannelNum <= 14) {
4601 chplan_new[k].ChannelNum =
4602 chplan_sta[i].ChannelNum;
4603 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4608 /* skip AP 2.4G channel plan */
4609 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
4613 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4615 if (i == MAX_CHANNEL_NUM ||
4616 chplan_sta[i].ChannelNum == 0)
4619 if (j == chplan_ap.Len ||
4620 chplan_ap.Channel[j] == 0)
4623 if (chplan_sta[i].ChannelNum ==
4624 chplan_ap.Channel[j]) {
4625 chplan_new[k].ChannelNum =
4626 chplan_ap.Channel[j];
4627 chplan_new[k].ScanType = SCAN_ACTIVE;
4631 } else if (chplan_sta[i].ChannelNum <
4632 chplan_ap.Channel[j]) {
4633 chplan_new[k].ChannelNum =
4634 chplan_sta[i].ChannelNum;
4635 chplan_new[k].ScanType = SCAN_PASSIVE;
4638 } else if (chplan_sta[i].ChannelNum >
4639 chplan_ap.Channel[j]) {
4640 chplan_new[k].ChannelNum =
4641 chplan_ap.Channel[j];
4642 chplan_new[k].ScanType = SCAN_ACTIVE;
4648 /* change AP not support channel to Passive scan */
4649 while (i < MAX_CHANNEL_NUM &&
4650 chplan_sta[i].ChannelNum != 0) {
4651 chplan_new[k].ChannelNum =
4652 chplan_sta[i].ChannelNum;
4653 chplan_new[k].ScanType = SCAN_PASSIVE;
4658 /* add channel AP supported */
4659 while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
4660 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4661 chplan_new[k].ScanType = SCAN_ACTIVE;
4666 /* keep original STA 5G channel plan */
4667 while (i < MAX_CHANNEL_NUM &&
4668 chplan_sta[i].ChannelNum != 0) {
4669 chplan_new[k].ChannelNum =
4670 chplan_sta[i].ChannelNum;
4671 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4676 pmlmeext->update_channel_plan_by_ap_done = 1;
4679 /* If channel is used by AP, set channel scan type to active */
4680 channel = bssid->DSConfig;
4681 chplan_new = pmlmeext->channel_set;
4683 while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
4684 if (chplan_new[i].ChannelNum == channel) {
4685 if (chplan_new[i].ScanType == SCAN_PASSIVE) {
4686 /* 5G Bnad 2, 3 (DFS) doesn't change
4688 if (channel >= 52 && channel <= 144)
4691 chplan_new[i].ScanType = SCAN_ACTIVE;
4692 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4693 "%s: change channel %d scan type from passive to active\n",
4702 /****************************************************************************
4704 Following are the functions to report events
4706 *****************************************************************************/
4708 void report_survey_event23a(struct rtw_adapter *padapter,
4709 struct recv_frame *precv_frame)
4711 struct cmd_obj *pcmd_obj;
4714 struct survey_event *psurvey_evt;
4715 struct C2HEvent_Header *pc2h_evt_hdr;
4716 struct mlme_ext_priv *pmlmeext;
4717 struct cmd_priv *pcmdpriv;
4722 pmlmeext = &padapter->mlmeextpriv;
4723 pcmdpriv = &padapter->cmdpriv;
4725 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4729 cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
4730 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4736 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4737 pcmd_obj->cmdsz = cmdsz;
4738 pcmd_obj->parmbuf = pevtcmd;
4740 pcmd_obj->rsp = NULL;
4741 pcmd_obj->rspsz = 0;
4743 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4744 pc2h_evt_hdr->len = sizeof(struct survey_event);
4745 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4746 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4748 psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4750 psurvey_evt->bss = collect_bss_info(padapter, precv_frame);
4751 if (!psurvey_evt->bss) {
4757 process_80211d(padapter, psurvey_evt->bss);
4759 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4761 pmlmeext->sitesurvey_res.bss_cnt++;
4766 void report_surveydone_event23a(struct rtw_adapter *padapter)
4768 struct cmd_obj *pcmd_obj;
4771 struct surveydone_event *psurveydone_evt;
4772 struct C2HEvent_Header *pc2h_evt_hdr;
4773 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4774 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4776 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4780 cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
4781 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4787 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4788 pcmd_obj->cmdsz = cmdsz;
4789 pcmd_obj->parmbuf = pevtcmd;
4791 pcmd_obj->rsp = NULL;
4792 pcmd_obj->rspsz = 0;
4794 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4795 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4796 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4797 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4799 psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4800 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4802 DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
4804 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4809 void report_join_res23a(struct rtw_adapter *padapter, int res)
4811 struct cmd_obj *pcmd_obj;
4814 struct joinbss_event *pjoinbss_evt;
4815 struct C2HEvent_Header *pc2h_evt_hdr;
4816 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4817 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4818 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4820 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4824 cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
4825 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4831 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4832 pcmd_obj->cmdsz = cmdsz;
4833 pcmd_obj->parmbuf = pevtcmd;
4835 pcmd_obj->rsp = NULL;
4836 pcmd_obj->rspsz = 0;
4838 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4839 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4840 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4841 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4843 pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4844 memcpy((unsigned char *)&pjoinbss_evt->network.network,
4845 &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
4846 pjoinbss_evt->network.join_res = res;
4848 DBG_8723A("report_join_res23a(%d)\n", res);
4850 rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
4852 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4857 void report_del_sta_event23a(struct rtw_adapter *padapter,
4858 unsigned char *MacAddr, unsigned short reason)
4860 struct cmd_obj *pcmd_obj;
4863 struct sta_info *psta;
4865 struct stadel_event *pdel_sta_evt;
4866 struct C2HEvent_Header *pc2h_evt_hdr;
4867 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4868 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4870 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4874 cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
4875 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4881 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4882 pcmd_obj->cmdsz = cmdsz;
4883 pcmd_obj->parmbuf = pevtcmd;
4885 pcmd_obj->rsp = NULL;
4886 pcmd_obj->rspsz = 0;
4888 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4889 pc2h_evt_hdr->len = sizeof(struct stadel_event);
4890 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4891 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4893 pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4894 ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
4895 memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
4898 psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
4900 mac_id = (int)psta->mac_id;
4904 pdel_sta_evt->mac_id = mac_id;
4906 DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
4908 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4913 void report_add_sta_event23a(struct rtw_adapter *padapter,
4914 unsigned char *MacAddr, int cam_idx)
4916 struct cmd_obj *pcmd_obj;
4919 struct stassoc_event *padd_sta_evt;
4920 struct C2HEvent_Header *pc2h_evt_hdr;
4921 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4922 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4924 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4928 cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
4929 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4935 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4936 pcmd_obj->cmdsz = cmdsz;
4937 pcmd_obj->parmbuf = pevtcmd;
4939 pcmd_obj->rsp = NULL;
4940 pcmd_obj->rspsz = 0;
4942 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4943 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4944 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4945 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4947 padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4948 ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
4949 padd_sta_evt->cam_id = cam_idx;
4951 DBG_8723A("report_add_sta_event23a: add STA\n");
4953 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4958 /****************************************************************************
4960 Following are the event callback functions
4962 *****************************************************************************/
4964 /* for sta/adhoc mode */
4965 void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
4967 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4968 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4969 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4972 VCS_update23a(padapter, psta);
4975 if (pmlmepriv->htpriv.ht_option) {
4976 psta->htpriv.ht_option = true;
4978 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4980 if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
4981 psta->htpriv.sgi = true;
4983 psta->qos_option = true;
4986 psta->htpriv.ht_option = false;
4988 psta->htpriv.ampdu_enable = false;
4990 psta->htpriv.sgi = false;
4991 psta->qos_option = false;
4994 psta->htpriv.bwmode = pmlmeext->cur_bwmode;
4995 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
4997 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
4998 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
5001 if (pmlmepriv->qos_option)
5002 psta->qos_option = true;
5004 psta->state = _FW_LINKED;
5007 void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter,
5010 struct sta_info *psta, *psta_bmc;
5011 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5012 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5013 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5014 struct sta_priv *pstapriv = &padapter->stapriv;
5017 hw_var_set_mlme_join(padapter, 1);
5018 hw_var_set_bssid(padapter, null_addr);
5020 /* restore to initial setting. */
5021 update_tx_basic_rate23a(padapter,
5022 padapter->registrypriv.wireless_mode);
5024 goto exit_mlmeext_joinbss_event_callback23a;
5027 if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
5029 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
5031 pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
5032 update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
5033 Update_RA_Entry23a(padapter, psta_bmc);
5037 /* turn on dynamic functions */
5038 rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
5040 /* update IOT-releated issue */
5041 update_IOT_info23a(padapter);
5043 HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
5046 rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
5048 /* update capability */
5049 update_capinfo23a(padapter, pmlmeinfo->capability);
5051 /* WMM, Update EDCA param */
5052 WMMOnAssocRsp23a(padapter);
5055 HTOnAssocRsp23a(padapter);
5057 /* Set cur_channel&cur_bwmode&cur_ch_offset */
5058 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5060 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
5061 if (psta) { /* only for infra. mode */
5062 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5064 /* DBG_8723A("set_sta_rate23a\n"); */
5066 psta->wireless_mode = pmlmeext->cur_wireless_mode;
5068 /* set per sta rate after updating HT cap. */
5069 set_sta_rate23a(padapter, psta);
5072 hw_var_set_mlme_join(padapter, 2);
5074 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
5075 /* correcting TSF */
5076 rtw_correct_TSF(padapter);
5078 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5081 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
5083 exit_mlmeext_joinbss_event_callback23a:
5084 DBG_8723A("=>%s\n", __func__);
5087 void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter,
5088 struct sta_info *psta)
5090 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5091 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5093 DBG_8723A("%s\n", __func__);
5095 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
5096 /* adhoc master or sta_count>1 */
5097 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5099 } else { /* adhoc client */
5100 /* correcting TSF */
5101 rtw_correct_TSF(padapter);
5104 if (send_beacon23a(padapter) != _SUCCESS) {
5105 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5107 pmlmeinfo->state ^= MSR_ADHOC;
5112 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
5114 hw_var_set_mlme_join(padapter, 2);
5117 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5119 /* rate radaptive */
5120 Update_RA_Entry23a(padapter, psta);
5122 /* update adhoc sta_info */
5123 update_sta_info23a(padapter, psta);
5126 void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
5128 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5129 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5131 if (is_client_associated_to_ap23a(padapter) ||
5132 is_IBSS_empty23a(padapter)) {
5133 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5135 hw_var_set_mlme_disconnect(padapter);
5136 hw_var_set_bssid(padapter, null_addr);
5138 /* restore to initial setting. */
5139 update_tx_basic_rate23a(padapter,
5140 padapter->registrypriv.wireless_mode);
5142 /* switch to the 20M Hz mode after disconnect */
5143 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5144 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5146 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5147 pmlmeext->cur_ch_offset,
5148 pmlmeext->cur_bwmode);
5150 flush_all_cam_entry23a(padapter);
5152 pmlmeinfo->state = MSR_NOLINK;
5154 /* set MSR to no link state -> infra. mode */
5155 rtl8723a_set_media_status(padapter, MSR_INFRA);
5157 del_timer_sync(&pmlmeext->link_timer);
5161 static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
5165 if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) &&
5166 sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
5167 sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
5172 sta_update_last_rx_pkts(psta);
5176 void linked_status_chk23a(struct rtw_adapter *padapter)
5179 struct sta_info *psta;
5180 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5181 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5182 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5183 struct sta_priv *pstapriv = &padapter->stapriv;
5185 if (is_client_associated_to_ap23a(padapter)) {
5186 /* linked infrastructure client mode */
5188 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5193 psta = rtw_get_stainfo23a(pstapriv,
5194 pmlmeinfo->network.MacAddress);
5196 bool is_p2p_enable = false;
5198 if (chk_ap_is_alive(padapter, psta) == false)
5201 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5204 if (pmlmeext->active_keep_alive_check &&
5205 (rx_chk == _FAIL || tx_chk == _FAIL)) {
5206 u8 backup_oper_channel = 0;
5208 /* switch to correct channel of current
5209 network before issue keep-alive frames */
5210 if (rtw_get_oper_ch23a(padapter) !=
5211 pmlmeext->cur_channel) {
5212 backup_oper_channel =
5213 rtw_get_oper_ch23a(padapter);
5214 SelectChannel23a(padapter,
5215 pmlmeext->cur_channel);
5218 if (rx_chk != _SUCCESS)
5219 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
5221 if ((tx_chk != _SUCCESS &&
5222 pmlmeinfo->link_count++ == 0xf) ||
5223 rx_chk != _SUCCESS) {
5224 tx_chk = issue_nulldata23a(padapter,
5227 /* if tx acked and p2p disabled,
5228 set rx_chk _SUCCESS to reset retry
5230 if (tx_chk == _SUCCESS &&
5235 /* back to the original operation channel */
5236 if (backup_oper_channel>0)
5237 SelectChannel23a(padapter,
5238 backup_oper_channel);
5240 if (rx_chk != _SUCCESS) {
5241 if (pmlmeext->retry == 0) {
5242 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5243 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5244 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5248 if (tx_chk != _SUCCESS &&
5249 pmlmeinfo->link_count++ == 0xf)
5250 tx_chk = issue_nulldata23a(padapter,
5255 if (rx_chk == _FAIL) {
5257 if (pmlmeext->retry > rx_chk_limit) {
5258 DBG_8723A_LEVEL(_drv_always_,
5259 "%s(%s): disconnect or "
5260 "roaming\n", __func__,
5261 padapter->pnetdev->name);
5262 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
5263 WLAN_REASON_EXPIRATION_CHK);
5267 pmlmeext->retry = 0;
5269 if (tx_chk == _FAIL)
5270 pmlmeinfo->link_count &= 0xf;
5272 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5273 pmlmeinfo->link_count = 0;
5277 } else if (is_client_associated_to_ibss23a(padapter)) {
5278 /* linked IBSS mode */
5279 /* for each assoc list entry to check the rx pkt counter */
5280 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5281 if (pmlmeinfo->FW_sta_info[i].status == 1) {
5282 psta = pmlmeinfo->FW_sta_info[i].psta;
5287 if (pmlmeinfo->FW_sta_info[i].rx_pkt ==
5288 sta_rx_pkts(psta)) {
5290 if (pmlmeinfo->FW_sta_info[i].retry<3) {
5291 pmlmeinfo->FW_sta_info[i].retry++;
5293 pmlmeinfo->FW_sta_info[i].retry = 0;
5294 pmlmeinfo->FW_sta_info[i].status = 0;
5295 report_del_sta_event23a(padapter, psta->hwaddr,
5296 65535/* indicate disconnect caused by no rx */
5300 pmlmeinfo->FW_sta_info[i].retry = 0;
5301 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5305 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5309 static void survey_timer_hdl(unsigned long data)
5311 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5312 struct cmd_obj *ph2c;
5313 struct sitesurvey_parm *psurveyPara;
5314 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5315 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5317 /* issue rtw_sitesurvey_cmd23a */
5318 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5319 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
5320 pmlmeext->sitesurvey_res.channel_idx++;
5322 if (pmlmeext->scan_abort == true) {
5323 pmlmeext->sitesurvey_res.channel_idx =
5324 pmlmeext->sitesurvey_res.ch_num;
5325 DBG_8723A("%s idx:%d\n", __func__,
5326 pmlmeext->sitesurvey_res.channel_idx);
5328 pmlmeext->scan_abort = false;/* reset */
5331 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
5333 goto exit_survey_timer_hdl;
5335 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm),
5339 goto exit_survey_timer_hdl;
5342 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
5343 GEN_CMD_CODE(_SiteSurvey));
5344 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
5347 exit_survey_timer_hdl:
5351 static void link_timer_hdl(unsigned long data)
5353 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5354 /* static unsigned int rx_pkt = 0; */
5355 /* static u64 tx_cnt = 0; */
5356 /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
5357 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5358 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5359 /* struct sta_priv *pstapriv = &padapter->stapriv; */
5361 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5362 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
5363 pmlmeinfo->state = MSR_NOLINK;
5364 report_join_res23a(padapter, -3);
5365 } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5367 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5368 /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5370 pmlmeinfo->state = 0;
5371 report_join_res23a(padapter, -1);
5376 /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5377 /* pmlmeinfo->reauth_count = 0; */
5381 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
5382 pmlmeinfo->auth_seq = 1;
5383 issue_auth(padapter, NULL, 0);
5384 set_link_timer(pmlmeext, REAUTH_TO);
5385 } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5386 /* re-assoc timer */
5387 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5388 pmlmeinfo->state = MSR_NOLINK;
5389 report_join_res23a(padapter, -2);
5393 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
5394 issue_assocreq(padapter);
5395 set_link_timer(pmlmeext, REASSOC_TO);
5401 static void addba_timer_hdl(unsigned long data)
5403 struct sta_info *psta = (struct sta_info *)data;
5404 struct ht_priv *phtpriv;
5409 phtpriv = &psta->htpriv;
5411 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5412 if (phtpriv->candidate_tid_bitmap)
5413 phtpriv->candidate_tid_bitmap = 0x0;
5417 void init_addba_retry_timer23a(struct sta_info *psta)
5419 setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
5420 (unsigned long)psta);
5423 void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
5425 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5427 setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
5428 (unsigned long)padapter);
5430 setup_timer(&pmlmeext->link_timer, link_timer_hdl,
5431 (unsigned long)padapter);
5434 int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5439 int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5441 enum nl80211_iftype type;
5442 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5443 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5444 const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5446 switch (psetop->mode) {
5447 case NL80211_IFTYPE_P2P_GO:
5448 case NL80211_IFTYPE_AP:
5449 pmlmeinfo->state = MSR_AP;
5452 case NL80211_IFTYPE_P2P_CLIENT:
5453 case NL80211_IFTYPE_STATION:
5455 pmlmeinfo->state &= ~(BIT(0)|BIT(1));
5456 /* set to STATION_STATE */
5457 pmlmeinfo->state |= MSR_INFRA;
5460 case NL80211_IFTYPE_ADHOC:
5468 hw_var_set_opmode(padapter, type);
5469 /* Set_NETYPE0_MSR(padapter, type); */
5474 int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5476 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5477 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5478 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5479 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5480 /* u32 initialgain; */
5482 if (pparm->ifmode == NL80211_IFTYPE_AP ||
5483 pparm->ifmode == NL80211_IFTYPE_P2P_GO) {
5484 #ifdef CONFIG_8723AU_AP_MODE
5485 if (pmlmeinfo->state == MSR_AP) {
5492 /* below is for ad-hoc master */
5493 if (pparm->ifmode == NL80211_IFTYPE_ADHOC) {
5494 rtw_joinbss_reset23a(padapter);
5496 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5497 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5498 pmlmeinfo->ERP_enable = 0;
5499 pmlmeinfo->WMM_enable = 0;
5500 pmlmeinfo->HT_enable = 0;
5501 pmlmeinfo->HT_caps_enable = 0;
5502 pmlmeinfo->HT_info_enable = 0;
5504 /* disable dynamic functions, such as high power, DIG */
5505 rtl8723a_odm_support_ability_backup(padapter);
5507 rtl8723a_odm_support_ability_clr(padapter,
5508 DYNAMIC_FUNC_DISABLE);
5510 /* cancel link timer */
5511 del_timer_sync(&pmlmeext->link_timer);
5514 flush_all_cam_entry23a(padapter);
5516 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5517 return H2C_PARAMETERS_ERROR;
5519 memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
5521 start_create_ibss(padapter);
5527 int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5529 struct registry_priv *pregpriv = &padapter->registrypriv;
5530 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5531 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5532 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5533 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5534 struct ieee80211_ht_operation *pht_info;
5537 /* u32 initialgain; */
5540 /* check already connecting to AP or not */
5541 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5542 if (pmlmeinfo->state & MSR_INFRA)
5543 issue_deauth_ex(padapter, pnetwork->MacAddress,
5544 WLAN_REASON_DEAUTH_LEAVING, 5, 100);
5546 pmlmeinfo->state = MSR_NOLINK;
5549 flush_all_cam_entry23a(padapter);
5551 del_timer_sync(&pmlmeext->link_timer);
5553 /* set MSR to nolink -> infra. mode */
5554 rtl8723a_set_media_status(padapter, MSR_INFRA);
5556 hw_var_set_mlme_disconnect(padapter);
5559 rtw_joinbss_reset23a(padapter);
5561 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5562 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5563 pmlmeinfo->ERP_enable = 0;
5564 pmlmeinfo->WMM_enable = 0;
5565 pmlmeinfo->HT_enable = 0;
5566 pmlmeinfo->HT_caps_enable = 0;
5567 pmlmeinfo->HT_info_enable = 0;
5568 pmlmeinfo->bwmode_updated = false;
5569 /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
5571 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5572 return H2C_PARAMETERS_ERROR;
5574 memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
5576 /* Check AP vendor to move rtw_joinbss_cmd23a() */
5577 /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
5578 pnetwork->IELength); */
5580 for (i = 0; i < pnetwork->IELength;) {
5581 p = pnetwork->IEs + i;
5584 case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
5585 if (!memcmp(p + 2, WMM_OUI23A, 4))
5586 pmlmeinfo->WMM_enable = 1;
5589 case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */
5590 pmlmeinfo->HT_caps_enable = 1;
5593 case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */
5594 pmlmeinfo->HT_info_enable = 1;
5596 /* spec case only for cisco's ap because cisco's ap
5597 * issue assoc rsp using mcs rate @40MHz or @20MHz */
5598 pht_info = (struct ieee80211_ht_operation *)(p + 2);
5600 if (pregpriv->cbw40_enable &&
5601 (pht_info->ht_param &
5602 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
5603 /* switch to the 40M Hz mode according to AP */
5604 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
5605 switch (pht_info->ht_param &
5606 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
5607 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
5608 pmlmeext->cur_ch_offset =
5609 HAL_PRIME_CHNL_OFFSET_LOWER;
5612 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
5613 pmlmeext->cur_ch_offset =
5614 HAL_PRIME_CHNL_OFFSET_UPPER;
5618 pmlmeext->cur_ch_offset =
5619 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5623 DBG_8723A("set ch/bw before connected\n");
5634 hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
5635 hw_var_set_mlme_join(padapter, 0);
5637 /* cancel link timer */
5638 del_timer_sync(&pmlmeext->link_timer);
5640 start_clnt_join(padapter);
5645 int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5647 const struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5648 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5649 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5650 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5652 if (is_client_associated_to_ap23a(padapter)) {
5653 issue_deauth_ex(padapter, pnetwork->MacAddress,
5654 WLAN_REASON_DEAUTH_LEAVING,
5655 param->deauth_timeout_ms/100, 100);
5658 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5660 /* pmlmeinfo->state = MSR_NOLINK; */
5662 hw_var_set_mlme_disconnect(padapter);
5663 hw_var_set_bssid(padapter, null_addr);
5665 /* restore to initial setting. */
5666 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
5668 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC ||
5669 (pmlmeinfo->state & 0x03) == MSR_AP)
5670 rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */
5672 /* set MSR to no link state -> infra. mode */
5673 rtl8723a_set_media_status(padapter, MSR_INFRA);
5675 pmlmeinfo->state = MSR_NOLINK;
5677 /* switch to the 20M Hz mode after disconnect */
5678 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5679 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5681 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5682 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5684 flush_all_cam_entry23a(padapter);
5686 del_timer_sync(&pmlmeext->link_timer);
5688 rtw_free_uc_swdec_pending_queue23a(padapter);
5694 rtw_scan_ch_decision(struct rtw_adapter *padapter,
5695 struct rtw_ieee80211_channel *out, u32 out_num,
5696 const struct rtw_ieee80211_channel *in, u32 in_num)
5699 int scan_ch_num = 0;
5701 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5703 /* clear out first */
5704 memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5706 /* acquire channels from in */
5708 for (i = 0;i<in_num;i++) {
5709 if (in[i].hw_value &&
5710 !(in[i].flags & IEEE80211_CHAN_DISABLED) &&
5711 (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set,
5712 in[i].hw_value)) >= 0) {
5713 memcpy(&out[j], &in[i],
5714 sizeof(struct rtw_ieee80211_channel));
5716 if (pmlmeext->channel_set[set_idx].ScanType ==
5718 out[j].flags &= IEEE80211_CHAN_NO_IR;
5726 /* if out is empty, use channel_set as default */
5728 for (i = 0;i<pmlmeext->max_chan_nums;i++) {
5729 out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
5731 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5732 out[i].flags &= IEEE80211_CHAN_NO_IR;
5738 if (padapter->setband == GHZ_24) { /* 2.4G */
5739 for (i = 0; i < j ; i++) {
5740 if (out[i].hw_value > 35)
5742 sizeof(struct rtw_ieee80211_channel));
5747 } else if (padapter->setband == GHZ_50) { /* 5G */
5748 for (i = 0; i < j ; i++) {
5749 if (out[i].hw_value > 35) {
5750 memcpy(&out[scan_ch_num++], &out[i],
5751 sizeof(struct rtw_ieee80211_channel));
5761 int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5763 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5764 const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
5765 u8 bdelayscan = false;
5769 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5770 pmlmeext->sitesurvey_res.state = SCAN_START;
5771 pmlmeext->sitesurvey_res.bss_cnt = 0;
5772 pmlmeext->sitesurvey_res.channel_idx = 0;
5774 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5775 if (pparm->ssid[i].ssid_len) {
5776 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
5777 pparm->ssid[i].ssid,
5778 IEEE80211_MAX_SSID_LEN);
5779 pmlmeext->sitesurvey_res.ssid[i].ssid_len =
5780 pparm->ssid[i].ssid_len;
5782 pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
5786 pmlmeext->sitesurvey_res.ch_num =
5787 rtw_scan_ch_decision(padapter,
5788 pmlmeext->sitesurvey_res.ch,
5789 RTW_CHANNEL_SCAN_AMOUNT,
5790 pparm->ch, pparm->ch_num);
5792 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5794 /* issue null data if associating to the AP */
5795 if (is_client_associated_to_ap23a(padapter)) {
5796 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5798 /* switch to correct channel of current network
5799 before issue keep-alive frames */
5800 if (rtw_get_oper_ch23a(padapter) !=
5801 pmlmeext->cur_channel)
5802 SelectChannel23a(padapter,
5803 pmlmeext->cur_channel);
5805 issue_nulldata23a(padapter, NULL, 1, 3, 500);
5811 /* delay 50ms to protect nulldata(1). */
5812 set_survey_timer(pmlmeext, 50);
5817 if (pmlmeext->sitesurvey_res.state == SCAN_START ||
5818 pmlmeext->sitesurvey_res.state == SCAN_TXNULL) {
5819 /* disable dynamic functions, such as high power, DIG */
5820 rtl8723a_odm_support_ability_backup(padapter);
5821 rtl8723a_odm_support_ability_clr(padapter,
5822 DYNAMIC_FUNC_DISABLE);
5824 /* config the initial gain under scanning, need to
5825 write the BB registers */
5826 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
5831 rtl8723a_set_initial_gain(padapter, initialgain);
5833 /* set MSR to no link state */
5834 rtl8723a_set_media_status(padapter, MSR_NOLINK);
5836 rtl8723a_mlme_sitesurvey(padapter, 1);
5838 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5841 rtw_site_survey(padapter);
5846 int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5848 const struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
5849 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5850 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5852 if (pparm->mode < 4)
5853 pmlmeinfo->auth_algo = pparm->mode;
5858 int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5860 unsigned short ctrl;
5861 const struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
5862 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5863 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5864 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5866 /* main tx key for wep. */
5868 pmlmeinfo->key_index = pparm->keyid;
5871 ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid;
5873 DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 "
5874 "WEP104-5 TKIP-2 AES-4) keyid:%d\n",
5875 pparm->algorithm, pparm->keyid);
5876 rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
5878 /* allow multicast packets to driver */
5879 rtl8723a_on_rcr_am(padapter);
5884 int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5887 u8 cam_id;/* cam_entry */
5888 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5889 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5890 const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
5893 /* 0~3 for default key */
5895 /* for concurrent mode (ap+sta): */
5896 /* default key is disable, using sw encrypt/decrypt */
5897 /* cam_entry = 4 for sta mode (macid = 0) */
5898 /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
5900 /* for concurrent mode (sta+sta): */
5901 /* default key is disable, using sw encrypt/decrypt */
5902 /* cam_entry = 4 mapping to macid = 0 */
5903 /* cam_entry = 5 mapping to macid = 2 */
5907 DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 "
5908 "WEP104-5 TKIP-2 AES-4) camid:%d\n",
5909 pparm->algorithm, cam_id);
5910 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
5911 struct sta_info *psta;
5912 struct sta_priv *pstapriv = &padapter->stapriv;
5914 if (pparm->algorithm == 0) { /* clear cam entry */
5915 clear_cam_entry23a(padapter, pparm->id);
5916 return H2C_SUCCESS_RSP;
5919 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
5921 ctrl = BIT(15) | (pparm->algorithm << 2);
5923 DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm "
5924 "=%d\n", pparm->algorithm);
5926 if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) {
5927 DBG_8723A("r871x_set_stakey_hdl23a():set_stakey"
5928 " failed, mac_id(aid) =%d\n",
5930 return H2C_REJECTED;
5933 /* 0~3 for default key, cmd_id = macid + 3,
5935 cam_id = psta->mac_id + 3;
5937 DBG_8723A("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, "
5938 "cam_entry =%d\n", pparm->addr[0],
5939 pparm->addr[1], pparm->addr[2],
5940 pparm->addr[3], pparm->addr[4],
5941 pparm->addr[5], cam_id);
5943 rtl8723a_cam_write(padapter, cam_id, ctrl,
5944 pparm->addr, pparm->key);
5946 return H2C_SUCCESS_RSP;
5948 DBG_8723A("r871x_set_stakey_hdl23a(): sta has been "
5950 return H2C_REJECTED;
5954 /* below for sta mode */
5956 if (pparm->algorithm == 0) { /* clear cam entry */
5957 clear_cam_entry23a(padapter, pparm->id);
5961 ctrl = BIT(15) | (pparm->algorithm << 2);
5963 rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5965 pmlmeinfo->enc_algo = pparm->algorithm;
5970 int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5972 const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
5973 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5974 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5975 struct sta_info *psta;
5977 psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
5982 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
5983 pmlmeinfo->HT_enable) ||
5984 (pmlmeinfo->state & 0x03) == MSR_AP) {
5985 issue_action_BA23a(padapter, pparm->addr,
5986 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5987 mod_timer(&psta->addba_retry_timer,
5988 jiffies + msecs_to_jiffies(ADDBA_TO));
5990 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
5995 int set_tx_beacon_cmd23a(struct rtw_adapter *padapter)
5997 struct cmd_obj *ph2c;
5998 struct Tx_Beacon_param *ptxBeacon_parm;
5999 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6000 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6001 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6005 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
6011 ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
6012 if (!ptxBeacon_parm) {
6018 memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
6019 sizeof(struct wlan_bssid_ex));
6021 len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs,
6022 ptxBeacon_parm->network.IELength,
6023 pmlmeinfo->hidden_ssid_mode);
6024 ptxBeacon_parm->network.IELength += len_diff;
6026 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm,
6027 GEN_CMD_CODE(_TX_Beacon));
6029 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
6035 int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6037 u8 evt_code, evt_seq;
6039 const struct C2HEvent_Header *c2h;
6040 void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf);
6042 c2h = (struct C2HEvent_Header *)pbuf;
6047 /* checking if event code is valid */
6048 if (evt_code >= MAX_C2HEVT) {
6049 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6050 "Event Code(%d) mismatch!\n", evt_code);
6054 /* checking if event size match the event parm size */
6055 if (wlanevents[evt_code].parmsize != 0 &&
6056 wlanevents[evt_code].parmsize != evt_sz) {
6057 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6058 "Event(%d) Parm Size mismatch (%d vs %d)!\n",
6059 evt_code, wlanevents[evt_code].parmsize, evt_sz);
6063 event_callback = wlanevents[evt_code].event_callback;
6064 event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header));
6071 int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6074 return H2C_PARAMETERS_ERROR;
6079 int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6081 if (send_beacon23a(padapter) == _FAIL) {
6082 DBG_8723A("issue_beacon23a, fail!\n");
6083 return H2C_PARAMETERS_ERROR;
6085 #ifdef CONFIG_8723AU_AP_MODE
6086 else { /* tx bc/mc frames after update TIM */
6087 struct sta_info *psta_bmc;
6088 struct list_head *plist, *phead, *ptmp;
6089 struct xmit_frame *pxmitframe;
6090 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6091 struct sta_priv *pstapriv = &padapter->stapriv;
6093 /* for BC/MC Frames */
6094 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
6098 if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) {
6099 msleep(10);/* 10ms, ATIM(HIQ) Windows */
6100 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
6101 spin_lock_bh(&pxmitpriv->lock);
6103 phead = get_list_head(&psta_bmc->sleep_q);
6105 list_for_each_safe(plist, ptmp, phead) {
6106 pxmitframe = container_of(plist,
6110 list_del_init(&pxmitframe->list);
6112 psta_bmc->sleepq_len--;
6113 if (psta_bmc->sleepq_len>0)
6114 pxmitframe->attrib.mdata = 1;
6116 pxmitframe->attrib.mdata = 0;
6118 pxmitframe->attrib.triggered = 1;
6120 pxmitframe->attrib.qsel = 0x11;/* HIQ */
6122 rtl8723au_hal_xmitframe_enqueue(padapter,
6126 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
6127 spin_unlock_bh(&pxmitpriv->lock);
6135 int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6137 const struct set_ch_parm *set_ch_parm;
6138 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6141 return H2C_PARAMETERS_ERROR;
6143 set_ch_parm = (struct set_ch_parm *)pbuf;
6145 DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__,
6146 padapter->pnetdev->name, set_ch_parm->ch,
6147 set_ch_parm->bw, set_ch_parm->ch_offset);
6149 pmlmeext->cur_channel = set_ch_parm->ch;
6150 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6151 pmlmeext->cur_bwmode = set_ch_parm->bw;
6153 set_channel_bwmode23a(padapter, set_ch_parm->ch,
6154 set_ch_parm->ch_offset, set_ch_parm->bw);
6159 int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6161 const struct SetChannelPlan_param *setChannelPlan_param;
6162 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6165 return H2C_PARAMETERS_ERROR;
6167 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6169 pmlmeext->max_chan_nums =
6170 init_channel_set(padapter, setChannelPlan_param->channel_plan,
6171 pmlmeext->channel_set);
6172 init_channel_list(padapter, pmlmeext->channel_set,
6173 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6178 int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6180 struct LedBlink_param *ledBlink_param;
6183 return H2C_PARAMETERS_ERROR;
6185 ledBlink_param = (struct LedBlink_param *)pbuf;
6190 int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6192 return H2C_REJECTED;
6195 /* TDLS_WRCR : write RCR DATA BIT */
6196 /* TDLS_SD_PTI : issue peer traffic indication */
6197 /* TDLS_CS_OFF : go back to the channel linked with AP,
6198 terminating channel switch procedure */
6199 /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and
6201 /* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */
6202 /* TDLS_OFF_CH : first time set channel to off channel */
6203 /* TDLS_BASE_CH : go back tp the channel linked with AP when set
6204 base channel as target channel */
6205 /* TDLS_P_OFF_CH : periodically go to off channel */
6206 /* TDLS_P_BASE_CH : periodically go back to base channel */
6207 /* TDLS_RS_RCR : restore RCR */
6208 /* TDLS_CKALV_PH1 : check alive timer phase1 */
6209 /* TDLS_CKALV_PH2 : check alive timer phase2 */
6210 /* TDLS_FREE_STA : free tdls sta */
6211 int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6213 return H2C_REJECTED;