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 u8 is_valid_p2p_probereq);
56 static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
57 unsigned short status);
58 static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
59 unsigned short reason, int try_cnt, int wait_ms);
60 static void start_clnt_assoc(struct rtw_adapter *padapter);
61 static void start_clnt_auth(struct rtw_adapter *padapter);
62 static void start_clnt_join(struct rtw_adapter *padapter);
63 static void start_create_ibss(struct rtw_adapter *padapter);
64 static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
65 struct recv_frame *precv_frame);
67 #ifdef CONFIG_8723AU_AP_MODE
68 static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
69 static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
70 struct sta_info *pstat, u16 pkt_type);
73 static struct mlme_handler mlme_sta_tbl[]={
74 {"OnAssocReq23a", &OnAssocReq23a},
75 {"OnAssocRsp23a", &OnAssocRsp23a},
76 {"OnReAssocReq", &OnAssocReq23a},
77 {"OnReAssocRsp", &OnAssocRsp23a},
78 {"OnProbeReq23a", &OnProbeReq23a},
79 {"OnProbeRsp23a", &OnProbeRsp23a},
81 /*----------------------------------------------------------
83 -----------------------------------------------------------*/
84 {"DoReserved23a", &DoReserved23a},
85 {"DoReserved23a", &DoReserved23a},
86 {"OnBeacon23a", &OnBeacon23a},
87 {"OnATIM", &OnAtim23a},
88 {"OnDisassoc23a", &OnDisassoc23a},
89 {"OnAuth23a", &OnAuth23aClient23a},
90 {"OnDeAuth23a", &OnDeAuth23a},
91 {"OnAction23a", &OnAction23a},
94 static struct action_handler OnAction23a_tbl[]={
95 {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a},
96 {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos},
97 {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls},
98 {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a},
99 {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a},
100 {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht},
101 {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a},
102 {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm},
103 {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p},
106 static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
108 /**************************************************
109 OUI definitions for the vendor specific IE
110 ***************************************************/
111 unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
112 unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
113 unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
114 unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
116 unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
117 unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
119 static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
121 /********************************************************
123 *********************************************************/
124 unsigned char MCS_rate_2R23A[16] = {
125 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
126 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
127 unsigned char MCS_rate_1R23A[16] = {
128 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
129 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
131 /********************************************************
132 ChannelPlan definitions
133 *********************************************************/
135 static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
136 /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
137 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
138 /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
139 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
140 /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
141 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
142 /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
143 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
144 /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
145 {{10, 11, 12, 13}, 4},
146 /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
150 static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
151 /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */
153 /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
154 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
155 116, 120, 124, 128, 132, 136, 140}, 19},
156 /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
157 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
158 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
159 /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
160 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
161 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},
162 /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
163 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
164 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
165 /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
166 {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},
167 /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
168 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},
169 /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
170 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},
171 /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
172 {{149, 153, 157, 161, 165}, 5},
173 /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
174 {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
175 /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
176 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
177 116, 136, 140, 149, 153, 157, 161, 165}, 20},
178 /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
179 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
180 116, 120, 124, 149, 153, 157, 161, 165}, 20},
181 /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
182 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
183 116, 120, 124, 128, 132, 136, 140}, 19},
184 /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
185 {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
186 /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
187 {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},
188 /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
189 {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149,
190 153, 157, 161, 165}, 15},
191 /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
192 {{56, 60, 64, 149, 153, 157, 161, 165}, 8},
194 /* Driver self defined for old channel plan Compatible,
195 Remember to modify if have new channel plan definition ===== */
196 /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */
197 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
198 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
199 /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
200 {{36, 40, 44, 48}, 4},
201 /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
202 {{36, 40, 44, 48, 149, 153, 157, 161}, 8},
205 static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
206 /* 0x00 ~ 0x1F , Old Define ===== */
207 {0x02, 0x11}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
208 {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
209 {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
210 {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
211 {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
212 {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
213 {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
214 {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
215 {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
216 {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
217 {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
218 {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
219 {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
220 {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
221 {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
222 {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
223 {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
224 {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
225 {0x01, 0x12}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
226 {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
227 {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
228 {0x00, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
229 {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
230 {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
231 {0x05, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
232 {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
233 {0x00, 0x00}, /* 0x1A, */
234 {0x00, 0x00}, /* 0x1B, */
235 {0x00, 0x00}, /* 0x1C, */
236 {0x00, 0x00}, /* 0x1D, */
237 {0x00, 0x00}, /* 0x1E, */
238 {0x05, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
239 /* 0x20 ~ 0x7F , New Define ===== */
240 {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
241 {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
242 {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
243 {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
244 {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
245 {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
246 {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
247 {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
248 {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
249 {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
250 {0x00, 0x00}, /* 0x2A, */
251 {0x00, 0x00}, /* 0x2B, */
252 {0x00, 0x00}, /* 0x2C, */
253 {0x00, 0x00}, /* 0x2D, */
254 {0x00, 0x00}, /* 0x2E, */
255 {0x00, 0x00}, /* 0x2F, */
256 {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
257 {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
258 {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
259 {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
260 {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
261 {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
262 {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
263 {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
264 {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
265 {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
266 {0x00, 0x00}, /* 0x3A, */
267 {0x00, 0x00}, /* 0x3B, */
268 {0x00, 0x00}, /* 0x3C, */
269 {0x00, 0x00}, /* 0x3D, */
270 {0x00, 0x00}, /* 0x3E, */
271 {0x00, 0x00}, /* 0x3F, */
272 {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
273 {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
276 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE =
277 {0x03, 0x02}; /* use the conbination for max channel numbers */
279 static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf)
283 static struct fwevent wlanevents[] =
285 {0, &dummy_event_callback}, /*0*/
293 {0, &rtw_survey_event_cb23a}, /*8*/
294 {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a},
295 {0, &rtw23a_joinbss_event_cb}, /*10*/
296 {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
297 {sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
298 {0, &dummy_event_callback},
299 {0, &dummy_event_callback},
304 {0, &dummy_event_callback},
308 {0, &dummy_event_callback},
313 static void rtw_correct_TSF(struct rtw_adapter *padapter)
315 hw_var_set_correct_tsf(padapter);
319 rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt)
321 pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp);
325 * Search the @param channel_num in given @param channel_set
326 * @ch_set: the given channel set
327 * @ch: the given channel number
329 * return the index of channel_num in channel_set, -1 if not found
331 int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch)
335 for (i = 0; ch_set[i]. ChannelNum != 0; i++) {
336 if (ch == ch_set[i].ChannelNum)
340 if (i >= ch_set[i].ChannelNum)
345 /****************************************************************************
347 Following are the initialization functions for WiFi MLME
349 *****************************************************************************/
351 int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
353 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
355 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
356 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
360 static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter)
362 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
363 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
364 unsigned char mixed_datarate[NumRates] = {
365 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
366 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
367 _48M_RATE_, _54M_RATE_, 0xff};
368 unsigned char mixed_basicrate[NumRates] = {
369 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
370 _12M_RATE_, _24M_RATE_, 0xff,};
372 atomic_set(&pmlmeext->event_seq, 0);
373 /* reset to zero when disconnect at client mode */
374 pmlmeext->mgnt_seq = 0;
376 pmlmeext->cur_channel = padapter->registrypriv.channel;
377 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
378 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
382 pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
384 memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
385 memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
387 if (pmlmeext->cur_channel > 14)
388 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
390 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
392 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
393 pmlmeext->sitesurvey_res.channel_idx = 0;
394 pmlmeext->sitesurvey_res.bss_cnt = 0;
395 pmlmeext->scan_abort = false;
397 pmlmeinfo->state = MSR_NOLINK;
398 pmlmeinfo->reauth_count = 0;
399 pmlmeinfo->reassoc_count = 0;
400 pmlmeinfo->link_count = 0;
401 pmlmeinfo->auth_seq = 0;
402 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
403 pmlmeinfo->key_index = 0;
406 pmlmeinfo->enc_algo = 0;
407 pmlmeinfo->authModeToggle = 0;
409 memset(pmlmeinfo->chg_txt, 0, 128);
411 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
412 pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
414 pmlmeinfo->dialogToken = 0;
416 pmlmeext->action_public_rxseq = 0xffff;
417 pmlmeext->action_public_dialog_token = 0xff;
420 static int has_channel(struct rt_channel_info *channel_set,
421 u8 chanset_size, u8 chan) {
424 for (i = 0; i < chanset_size; i++) {
425 if (channel_set[i].ChannelNum == chan)
432 static void init_channel_list(struct rtw_adapter *padapter,
433 struct rt_channel_info *channel_set,
435 struct p2p_channels *channel_list)
437 struct p2p_oper_class_map op_class[] = {
438 { IEEE80211G, 81, 1, 13, 1, BW20 },
439 { IEEE80211G, 82, 14, 14, 1, BW20 },
440 { IEEE80211A, 115, 36, 48, 4, BW20 },
441 { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
442 { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
443 { IEEE80211A, 124, 149, 161, 4, BW20 },
444 { IEEE80211A, 125, 149, 169, 4, BW20 },
445 { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
446 { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
447 { -1, 0, 0, 0, 0, BW20 }
454 for (op = 0; op_class[op].op_class; op++) {
456 struct p2p_oper_class_map *o = &op_class[op];
457 struct p2p_reg_class *reg = NULL;
459 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
460 if (!has_channel(channel_set, chanset_size, ch))
463 if ((0 == padapter->registrypriv.ht_enable) &&
467 if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
468 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
472 reg = &channel_list->reg_class[cla];
474 reg->reg_class = o->op_class;
477 reg->channel[reg->channels] = ch;
481 channel_list->reg_classes = cla;
484 static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan,
485 struct rt_channel_info *c_set)
488 u8 b5GBand = false, b2_4GBand = false;
489 u8 Index2G = 0, Index5G = 0;
491 memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
493 if (cplan >= RT_CHANNEL_DOMAIN_MAX &&
494 cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
495 DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan);
499 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
501 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
502 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
504 Index2G = RTW_ChannelPlanMap[cplan].Index2G;
507 if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
509 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
510 Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
512 Index5G = RTW_ChannelPlanMap[cplan].Index5G;
516 for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) {
517 c_set[ch_size].ChannelNum =
518 RTW_ChannelPlan2G[Index2G].Channel[i];
520 if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) ||
521 /* Channel 1~11 is active, and 12~14 is passive */
522 RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) {
523 if (c_set[ch_size].ChannelNum >= 1 &&
524 c_set[ch_size].ChannelNum <= 11)
525 c_set[ch_size].ScanType = SCAN_ACTIVE;
526 else if (c_set[ch_size].ChannelNum >= 12 &&
527 c_set[ch_size].ChannelNum <= 14)
528 c_set[ch_size].ScanType = SCAN_PASSIVE;
529 } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan ||
530 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan ||
531 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
532 /* channel 12~13, passive scan */
533 if (c_set[ch_size].ChannelNum <= 11)
534 c_set[ch_size].ScanType = SCAN_ACTIVE;
536 c_set[ch_size].ScanType = SCAN_PASSIVE;
538 c_set[ch_size].ScanType = SCAN_ACTIVE;
545 for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) {
546 if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 ||
547 RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) {
548 c_set[ch_size].ChannelNum =
549 RTW_ChannelPlan5G[Index5G].Channel[i];
550 if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) {
551 /* passive scan for all 5G channels */
552 c_set[ch_size].ScanType =
555 c_set[ch_size].ScanType =
557 DBG_8723A("%s(): channel_set[%d].ChannelNum = "
558 "%d\n", __func__, ch_size,
559 c_set[ch_size].ChannelNum);
568 int init_mlme_ext_priv23a(struct rtw_adapter *padapter)
570 struct registry_priv *pregistrypriv = &padapter->registrypriv;
571 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
572 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
573 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
575 pmlmeext->padapter = padapter;
577 init_mlme_ext_priv23a_value(padapter);
578 pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
580 init_mlme_ext_timer23a(padapter);
582 #ifdef CONFIG_8723AU_AP_MODE
583 init_mlme_ap_info23a(padapter);
586 pmlmeext->max_chan_nums = init_channel_set(padapter,
587 pmlmepriv->ChannelPlan,
588 pmlmeext->channel_set);
589 init_channel_list(padapter, pmlmeext->channel_set,
590 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
592 pmlmeext->chan_scan_time = SURVEY_TO;
593 pmlmeext->mlmeext_init = true;
595 pmlmeext->active_keep_alive_check = true;
599 void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext)
601 struct rtw_adapter *padapter = pmlmeext->padapter;
606 if (padapter->bDriverStopped == true) {
607 del_timer_sync(&pmlmeext->survey_timer);
608 del_timer_sync(&pmlmeext->link_timer);
609 /* del_timer_sync(&pmlmeext->ADDBA_timer); */
614 _mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable,
615 struct recv_frame *precv_frame)
617 struct sk_buff *skb = precv_frame->pkt;
618 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
621 /* receive the frames that ra(a1) is my address
622 or ra(a1) is bc address. */
623 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&&
624 !is_broadcast_ether_addr(hdr->addr1))
627 ptable->func(padapter, precv_frame);
631 void mgt_dispatcher23a(struct rtw_adapter *padapter,
632 struct recv_frame *precv_frame)
634 struct mlme_handler *ptable;
635 #ifdef CONFIG_8723AU_AP_MODE
636 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
637 #endif /* CONFIG_8723AU_AP_MODE */
638 struct sk_buff *skb = precv_frame->pkt;
639 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
640 struct sta_info *psta;
644 if (!ieee80211_is_mgmt(mgmt->frame_control))
647 /* receive the frames that ra(a1) is my address or ra(a1) is
649 if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) &&
650 !is_broadcast_ether_addr(mgmt->da))
653 ptable = mlme_sta_tbl;
655 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
659 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
660 "Currently we do not support reserved sub-fr-type =%d\n",
666 psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa);
669 if (ieee80211_has_retry(mgmt->frame_control)) {
670 if (precv_frame->attrib.seq_num ==
671 psta->RxMgmtFrameSeqNum) {
672 /* drop the duplicate management frame */
673 DBG_8723A("Drop duplicate management frame "
674 "with seq_num = %d.\n",
675 precv_frame->attrib.seq_num);
679 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
682 #ifdef CONFIG_8723AU_AP_MODE
684 case IEEE80211_STYPE_AUTH:
685 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
686 ptable->func = &OnAuth23a;
688 ptable->func = &OnAuth23aClient23a;
690 case IEEE80211_STYPE_ASSOC_REQ:
691 case IEEE80211_STYPE_REASSOC_REQ:
692 _mgt_dispatcher23a(padapter, ptable, precv_frame);
694 case IEEE80211_STYPE_PROBE_REQ:
695 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
696 _mgt_dispatcher23a(padapter, ptable, precv_frame);
698 _mgt_dispatcher23a(padapter, ptable, precv_frame);
700 case IEEE80211_STYPE_BEACON:
701 _mgt_dispatcher23a(padapter, ptable, precv_frame);
703 case IEEE80211_STYPE_ACTION:
704 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
705 _mgt_dispatcher23a(padapter, ptable, precv_frame);
708 _mgt_dispatcher23a(padapter, ptable, precv_frame);
712 _mgt_dispatcher23a(padapter, ptable, precv_frame);
716 /****************************************************************************
718 Following are the callback functions for each subtype of the management frames
720 *****************************************************************************/
723 OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
726 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
727 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
728 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
729 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
730 struct sk_buff *skb = precv_frame->pkt;
731 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
734 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
737 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
738 !check_fwstate(pmlmepriv,
739 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
742 if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) {
743 printk(KERN_WARNING "%s: Received non probe request frame\n",
748 len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
750 ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len);
752 /* check (wildcard) SSID */
756 if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) ||
757 (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) {
761 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
762 pmlmepriv->cur_network.join_res)
763 issue_probersp(padapter, mgmt->sa, false);
770 OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
772 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
774 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
775 report_survey_event23a(padapter, precv_frame);
783 OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
786 struct sta_info *psta;
787 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
788 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
789 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
790 struct sta_priv *pstapriv = &padapter->stapriv;
791 struct sk_buff *skb = precv_frame->pkt;
792 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
793 int pkt_len = skb->len;
794 struct wlan_bssid_ex *pbss;
800 pie = mgmt->u.beacon.variable;
801 pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
802 p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len);
803 if (p && ielen > 0) {
804 if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) {
805 /* Invalid value 0x2D is detected in Extended Supported
806 * Rates (ESR) IE. Try to fix the IE length to avoid
807 * failed Beacon parsing.
809 DBG_8723A("[WIFIDBG] Error in ESR IE is detected in "
810 "Beacon of BSSID: %pM. Fix the length of "
811 "ESR IE to avoid failed Beacon parsing.\n",
817 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
818 report_survey_event23a(padapter, precv_frame);
822 if (!ether_addr_equal(mgmt->bssid,
823 get_my_bssid23a(&pmlmeinfo->network)))
826 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
827 /* we should update current network before auth,
828 or some IE is wrong */
829 pbss = collect_bss_info(padapter, precv_frame);
831 update_network23a(&pmlmepriv->cur_network.network, pbss,
833 rtw_get_bcn_info23a(&pmlmepriv->cur_network);
837 /* check the vendor of the assoc AP */
838 pmlmeinfo->assoc_AP_vendor =
839 check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len -
840 offsetof(struct ieee80211_mgmt, u));
842 /* update TSF Value */
843 rtw_update_TSF(pmlmeext, mgmt);
846 start_clnt_auth(padapter);
851 if (((pmlmeinfo->state & 0x03) == MSR_AP) &&
852 (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
853 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
855 ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len);
856 if (ret != _SUCCESS) {
857 DBG_8723A_LEVEL(_drv_always_, "ap has changed, "
859 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
862 /* update WMM, ERP in the beacon */
863 /* todo: the timer is used instead of
864 the number of the beacon received */
865 if ((sta_rx_pkts(psta) & 0xf) == 0) {
866 /* DBG_8723A("update_bcn_info\n"); */
867 update_beacon23a_info(padapter, mgmt,
871 } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
872 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
874 /* update WMM, ERP in the beacon */
875 /* todo: the timer is used instead of the
876 number of the beacon received */
877 if ((sta_rx_pkts(psta) & 0xf) == 0) {
878 /* DBG_8723A("update_bcn_info\n"); */
879 update_beacon23a_info(padapter, mgmt,
883 /* allocate a new CAM entry for IBSS station */
884 cam_idx = allocate_fw_sta_entry23a(padapter);
885 if (cam_idx == NUM_STA)
888 /* get supported rate */
889 if (update_sta_support_rate23a(padapter, pie, pie_len,
891 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
895 /* update TSF Value */
896 rtw_update_TSF(pmlmeext, mgmt);
898 /* report sta add event */
899 report_add_sta_event23a(padapter, mgmt->sa,
909 #ifdef CONFIG_8723AU_AP_MODE
911 OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
913 static struct sta_info stat;
914 struct sta_info *pstat = NULL;
915 struct sta_priv *pstapriv = &padapter->stapriv;
916 struct security_priv *psecuritypriv = &padapter->securitypriv;
917 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
918 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
919 struct sk_buff *skb = precv_frame->pkt;
920 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
924 u16 auth_mode, seq, algorithm;
925 int status, len = skb->len;
927 if ((pmlmeinfo->state & 0x03) != MSR_AP)
930 DBG_8723A("+OnAuth23a\n");
934 auth_mode = psecuritypriv->dot11AuthAlgrthm;
936 pframe = mgmt->u.auth.variable;
937 len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable);
939 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
940 algorithm = le16_to_cpu(mgmt->u.auth.auth_alg);
942 DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
944 if (auth_mode == 2 &&
945 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 &&
946 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104)
949 /* rx a shared-key auth but shared not enabled, or */
950 /* rx a open-system auth but shared-key is enabled */
951 if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) ||
952 (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) {
953 DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib "
954 "=%d] %02X%02X%02X%02X%02X%02X\n",
955 algorithm, auth_mode,
956 sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
958 status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
963 if (rtw_access_ctrl23a(padapter, sa) == false) {
964 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
968 pstat = rtw_get_stainfo23a(pstapriv, sa);
970 /* allocate a new one */
971 DBG_8723A("going to alloc stainfo for sa =%pM\n", sa);
972 pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC);
974 DBG_8723A(" Exceed the upper limit of supported "
976 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
980 pstat->state = WIFI_FW_AUTH_NULL;
983 /* pstat->flags = 0; */
984 /* pstat->capability = 0; */
986 spin_lock_bh(&pstapriv->asoc_list_lock);
987 if (!list_empty(&pstat->asoc_list)) {
988 list_del_init(&pstat->asoc_list);
989 pstapriv->asoc_list_cnt--;
990 if (pstat->expire_to > 0) {
991 /* TODO: STA re_auth within expire_to */
994 spin_unlock_bh(&pstapriv->asoc_list_lock);
997 /* TODO: STA re_auth and auth timeout */
1001 spin_lock_bh(&pstapriv->auth_list_lock);
1002 if (list_empty(&pstat->auth_list)) {
1003 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
1004 pstapriv->auth_list_cnt++;
1006 spin_unlock_bh(&pstapriv->auth_list_lock);
1008 if (pstat->auth_seq == 0)
1009 pstat->expire_to = pstapriv->auth_to;
1011 if ((pstat->auth_seq + 1) != seq) {
1012 DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, "
1013 "exp_seq =%d]!\n", seq, pstat->auth_seq+1);
1014 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1018 if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) {
1020 pstat->state &= ~WIFI_FW_AUTH_NULL;
1021 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1022 pstat->expire_to = pstapriv->assoc_to;
1023 pstat->authalg = algorithm;
1025 DBG_8723A("(2)auth rejected because out of seq "
1026 "[rx_seq =%d, exp_seq =%d]!\n",
1027 seq, pstat->auth_seq+1);
1028 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1031 } else { /* shared system or auto authentication */
1033 /* prepare for the challenging txt... */
1034 pstat->state &= ~WIFI_FW_AUTH_NULL;
1035 pstat->state |= WIFI_FW_AUTH_STATE;
1036 pstat->authalg = algorithm;
1037 pstat->auth_seq = 2;
1038 } else if (seq == 3) {
1039 /* checking for challenging txt... */
1040 DBG_8723A("checking for challenging txt...\n");
1042 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len);
1043 if (!p || p[1] <= 0) {
1044 DBG_8723A("auth rejected because challenge "
1046 status = WLAN_STATUS_CHALLENGE_FAIL;
1050 if (!memcmp(p + 2, pstat->chg_txt, 128)) {
1051 pstat->state &= ~WIFI_FW_AUTH_STATE;
1052 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1053 /* challenging txt is correct... */
1054 pstat->expire_to = pstapriv->assoc_to;
1056 DBG_8723A("auth rejected because challenge "
1058 status = WLAN_STATUS_CHALLENGE_FAIL;
1062 DBG_8723A("(3)auth rejected because out of seq "
1063 "[rx_seq =%d, exp_seq =%d]!\n",
1064 seq, pstat->auth_seq+1);
1065 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1070 /* Now, we are going to issue_auth... */
1071 pstat->auth_seq = seq + 1;
1073 issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS);
1075 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1076 pstat->auth_seq = 0;
1083 rtw_free_stainfo23a(padapter, pstat);
1086 memset((char *)pstat, '\0', sizeof(stat));
1087 pstat->auth_seq = 2;
1088 ether_addr_copy(pstat->hwaddr, sa);
1090 issue_auth(padapter, pstat, (unsigned short)status);
1097 OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1099 unsigned int seq, status, algthm;
1100 unsigned int go2asoc = 0;
1101 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1102 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1103 struct sk_buff *skb = precv_frame->pkt;
1104 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1107 int plen = skb->len;
1109 DBG_8723A("%s\n", __func__);
1111 /* check A1 matches or not */
1112 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
1115 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1118 pie = mgmt->u.auth.variable;
1119 plen -= offsetof(struct ieee80211_mgmt, u.auth.variable);
1121 algthm = le16_to_cpu(mgmt->u.auth.auth_alg);
1122 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
1123 status = le16_to_cpu(mgmt->u.auth.status_code);
1126 DBG_8723A("clnt auth fail, status: %d\n", status);
1127 /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
1128 if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
1129 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1130 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1132 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1133 /* pmlmeinfo->reauth_count = 0; */
1136 set_link_timer(pmlmeext, 1);
1141 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1142 /* legendary shared system */
1143 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen);
1146 /* DBG_8723A("marc: no challenge text?\n"); */
1150 memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]);
1151 pmlmeinfo->auth_seq = 3;
1152 issue_auth(padapter, NULL, 0);
1153 set_link_timer(pmlmeext, REAUTH_TO);
1160 } else if (seq == 4) {
1161 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1166 /* this is also illegal */
1167 /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n",
1173 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
1174 start_clnt_assoc(padapter);
1180 /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1185 #ifdef CONFIG_8723AU_AP_MODE
1186 static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen)
1190 /* first 3 bytes in vendor specific information element are the IEEE
1191 * OUI of the vendor. The following byte is used a vendor specific
1194 DBG_8723A("short vendor specific information element "
1195 "ignored (len =%i)\n", elen);
1199 oui = RTW_GET_BE24(pos);
1201 case WLAN_OUI_MICROSOFT:
1202 /* Microsoft/Wi-Fi information elements are further typed and
1205 case WLAN_OUI_TYPE_MICROSOFT_WPA:
1206 /* Microsoft OUI (00:50:F2) with OUI Type 1:
1207 * real WPA information element */
1209 case WLAN_OUI_TYPE_MICROSOFT_WMM:
1211 DBG_8723A("short WME information element "
1212 "ignored (len =%i)\n", elen);
1216 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
1217 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
1219 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
1222 DBG_8723A("unknown WME information element "
1223 "ignored (subtype =%d len =%i)\n",
1228 case WLAN_OUI_TYPE_MICROSOFT_WPS:
1229 /* Wi-Fi Protected Setup (WPS) IE */
1232 DBG_8723A("Unknown Microsoft information element "
1233 "ignored (type =%d len =%i)\n",
1241 case VENDOR_HT_CAPAB_OUI_TYPE:
1244 DBG_8723A("Unknown Broadcom information element "
1245 "ignored (type =%d len =%i)\n", pos[3], elen);
1251 DBG_8723A("unknown vendor specific information element "
1252 "ignored (vendor OUI %02x:%02x:%02x len =%i)\n",
1253 pos[0], pos[1], pos[2], elen);
1260 static int rtw_validate_frame_ies(const u8 *start, uint len)
1262 const u8 *pos = start;
1274 DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d "
1275 "left =%i)\n", __func__, id, elen, left);
1281 case WLAN_EID_SUPP_RATES:
1282 case WLAN_EID_FH_PARAMS:
1283 case WLAN_EID_DS_PARAMS:
1284 case WLAN_EID_CF_PARAMS:
1286 case WLAN_EID_IBSS_PARAMS:
1287 case WLAN_EID_CHALLENGE:
1288 case WLAN_EID_ERP_INFO:
1289 case WLAN_EID_EXT_SUPP_RATES:
1291 case WLAN_EID_VENDOR_SPECIFIC:
1292 if (rtw_validate_vendor_specific_ies(pos, elen))
1296 case WLAN_EID_PWR_CAPABILITY:
1297 case WLAN_EID_SUPPORTED_CHANNELS:
1298 case WLAN_EID_MOBILITY_DOMAIN:
1299 case WLAN_EID_FAST_BSS_TRANSITION:
1300 case WLAN_EID_TIMEOUT_INTERVAL:
1301 case WLAN_EID_HT_CAPABILITY:
1302 case WLAN_EID_HT_OPERATION:
1305 DBG_8723A("%s IEEE 802.11 ignored unknown element "
1306 "(id =%d elen =%d)\n", __func__, id, elen);
1322 OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1324 #ifdef CONFIG_8723AU_AP_MODE
1325 u16 capab_info, listen_interval;
1326 struct sta_info *pstat;
1327 unsigned char reassoc;
1328 int i, wpa_ie_len, left;
1329 unsigned char supportRate[16];
1331 unsigned short status = WLAN_STATUS_SUCCESS;
1332 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1333 struct security_priv *psecuritypriv = &padapter->securitypriv;
1334 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1335 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1336 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
1337 struct sta_priv *pstapriv = &padapter->stapriv;
1338 struct sk_buff *skb = precv_frame->pkt;
1339 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1340 const u8 *pos, *p, *wpa_ie, *wps_ie;
1341 u8 *pframe = skb->data;
1342 uint pkt_len = skb->len;
1345 if ((pmlmeinfo->state & 0x03) != MSR_AP)
1348 left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
1349 if (ieee80211_is_assoc_req(mgmt->frame_control)) {
1351 pos = mgmt->u.assoc_req.variable;
1352 left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
1353 } else { /* WIFI_REASSOCREQ */
1355 pos = mgmt->u.reassoc_req.variable;
1356 left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable);
1360 DBG_8723A("handle_assoc(reassoc =%d) - too short payload "
1361 "(len =%lu)\n", reassoc, (unsigned long)pkt_len);
1365 pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1367 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1368 goto asoc_class2_error;
1371 /* These two are located at the same offsets whether it's an
1372 * assoc_req or a reassoc_req */
1373 capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info);
1375 get_unaligned_le16(&mgmt->u.assoc_req.listen_interval);
1377 DBG_8723A("%s\n", __func__);
1379 /* check if this stat has been successfully authenticated/assocated */
1380 if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) {
1381 if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) {
1382 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1383 goto asoc_class2_error;
1385 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1386 pstat->state |= WIFI_FW_ASSOC_STATE;
1389 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1390 pstat->state |= WIFI_FW_ASSOC_STATE;
1393 pstat->capability = capab_info;
1395 /* now parse all ieee802_11 ie to point to elems */
1397 if (rtw_validate_frame_ies(pos, left)) {
1398 DBG_8723A("STA %pM sent invalid association request\n",
1400 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1401 goto OnAssocReq23aFail;
1404 /* now we should check all the fields... */
1406 p = cfg80211_find_ie(WLAN_EID_SSID, pos, left);
1407 if (!p || p[1] == 0) {
1408 /* broadcast ssid, however it is not allowed in assocreq */
1409 DBG_8723A("STA %pM sent invalid association request lacking an SSID\n",
1411 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1412 goto OnAssocReq23aFail;
1414 /* check if ssid match */
1415 if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len))
1416 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1418 if (p[1] != cur->Ssid.ssid_len)
1419 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1422 if (status != WLAN_STATUS_SUCCESS)
1423 goto OnAssocReq23aFail;
1425 /* check if the supported rate is ok */
1426 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left);
1428 DBG_8723A("Rx a sta assoc-req which supported rate is "
1430 /* use our own rate set as statoin used */
1431 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1432 /* supportRateNum = AP_BSSRATE_LEN; */
1434 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1435 goto OnAssocReq23aFail;
1437 memcpy(supportRate, p + 2, p[1]);
1438 supportRateNum = p[1];
1440 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left);
1442 if (supportRateNum <= sizeof(supportRate)) {
1443 memcpy(supportRate+supportRateNum, p + 2, p[1]);
1444 supportRateNum += p[1];
1449 /* todo: mask supportRate between AP & STA -> move to update raid */
1450 /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1452 /* update station supportRate */
1453 pstat->bssratelen = supportRateNum;
1454 memcpy(pstat->bssrateset, supportRate, supportRateNum);
1455 Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1457 /* check RSN/WPA/WPS */
1458 pstat->dot8021xalg = 0;
1460 pstat->wpa_group_cipher = 0;
1461 pstat->wpa2_group_cipher = 0;
1462 pstat->wpa_pairwise_cipher = 0;
1463 pstat->wpa2_pairwise_cipher = 0;
1464 memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1466 wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left);
1468 wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1469 WLAN_OUI_TYPE_MICROSOFT_WPA,
1472 int group_cipher = 0, pairwise_cipher = 0;
1474 wpa_ie_len = wpa_ie[1];
1475 if (psecuritypriv->wpa_psk & BIT(1)) {
1476 r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2,
1478 &pairwise_cipher, NULL);
1479 if (r == _SUCCESS) {
1480 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1481 pstat->wpa_psk |= BIT(1);
1483 pstat->wpa2_group_cipher = group_cipher &
1484 psecuritypriv->wpa2_group_cipher;
1485 pstat->wpa2_pairwise_cipher = pairwise_cipher &
1486 psecuritypriv->wpa2_pairwise_cipher;
1488 status = WLAN_STATUS_INVALID_IE;
1489 } else if (psecuritypriv->wpa_psk & BIT(0)) {
1490 r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2,
1491 &group_cipher, &pairwise_cipher,
1493 if (r == _SUCCESS) {
1494 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1495 pstat->wpa_psk |= BIT(0);
1497 pstat->wpa_group_cipher = group_cipher &
1498 psecuritypriv->wpa_group_cipher;
1499 pstat->wpa_pairwise_cipher = pairwise_cipher &
1500 psecuritypriv->wpa_pairwise_cipher;
1502 status = WLAN_STATUS_INVALID_IE;
1507 if (wpa_ie && status == WLAN_STATUS_SUCCESS) {
1508 if (!pstat->wpa_group_cipher)
1509 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1511 if (!pstat->wpa_pairwise_cipher)
1512 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1516 if (status != WLAN_STATUS_SUCCESS)
1517 goto OnAssocReq23aFail;
1519 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1521 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1522 WLAN_OUI_TYPE_MICROSOFT_WPS,
1527 DBG_8723A("STA included WPS IE in (Re)Association "
1528 "Request - assume WPS is used\n");
1529 pstat->flags |= WLAN_STA_WPS;
1531 DBG_8723A("STA did not include WPA/RSN IE in (Re)"
1532 "Association Request - possible WPS use\n");
1533 pstat->flags |= WLAN_STA_MAYBE_WPS;
1538 if (psecuritypriv->wpa_psk == 0) {
1539 DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
1542 status = WLAN_STATUS_INVALID_IE;
1544 goto OnAssocReq23aFail;
1548 DBG_8723A("STA included WPS IE in (Re)Association "
1549 "Request - WPS is used\n");
1550 pstat->flags |= WLAN_STA_WPS;
1553 copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ?
1554 sizeof(pstat->wpa_ie) : (wpa_ie_len + 2);
1558 memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
1561 /* check if there is WMM IE & support WWM-PS */
1562 pstat->flags &= ~WLAN_STA_WME;
1563 pstat->qos_option = 0;
1564 pstat->qos_info = 0;
1565 pstat->has_legacy_ac = true;
1566 pstat->uapsd_vo = 0;
1567 pstat->uapsd_vi = 0;
1568 pstat->uapsd_be = 0;
1569 pstat->uapsd_bk = 0;
1570 if (pmlmepriv->qos_option) {
1571 const u8 *end = pos + left;
1577 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1578 WLAN_OUI_TYPE_MICROSOFT_WMM,
1581 pstat->flags |= WLAN_STA_WME;
1583 pstat->qos_option = 1;
1584 pstat->qos_info = *(p + 8);
1587 (pstat->qos_info >> 5) & 0x3;
1589 if ((pstat->qos_info & 0xf) != 0xf)
1590 pstat->has_legacy_ac = true;
1592 pstat->has_legacy_ac = false;
1594 if (pstat->qos_info & 0xf) {
1595 if (pstat->qos_info & BIT(0))
1596 pstat->uapsd_vo = BIT(0)|BIT(1);
1598 pstat->uapsd_vo = 0;
1600 if (pstat->qos_info & BIT(1))
1601 pstat->uapsd_vi = BIT(0)|BIT(1);
1603 pstat->uapsd_vi = 0;
1605 if (pstat->qos_info & BIT(2))
1606 pstat->uapsd_bk = BIT(0)|BIT(1);
1608 pstat->uapsd_bk = 0;
1610 if (pstat->qos_info & BIT(3))
1611 pstat->uapsd_be = BIT(0)|BIT(1);
1613 pstat->uapsd_be = 0;
1624 /* save HT capabilities in the sta object */
1625 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1626 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left);
1628 if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) {
1629 pstat->flags |= WLAN_STA_HT;
1631 pstat->flags |= WLAN_STA_WME;
1633 memcpy(&pstat->htpriv.ht_cap, p + 2,
1634 sizeof(struct ieee80211_ht_cap));
1636 pstat->flags &= ~WLAN_STA_HT;
1638 if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){
1639 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1640 goto OnAssocReq23aFail;
1643 if (pstat->flags & WLAN_STA_HT &&
1644 (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP ||
1645 pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
1646 DBG_8723A("HT: %pM tried to use TKIP with HT association\n",
1649 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1650 /* goto OnAssocReq23aFail; */
1653 pstat->flags |= WLAN_STA_NONERP;
1654 for (i = 0; i < pstat->bssratelen; i++) {
1655 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1656 pstat->flags &= ~WLAN_STA_NONERP;
1661 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1662 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1664 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1666 if (status != WLAN_STATUS_SUCCESS)
1667 goto OnAssocReq23aFail;
1669 /* TODO: identify_proprietary_vendor_ie(); */
1670 /* Realtek proprietary IE */
1671 /* identify if this is Broadcom sta */
1672 /* identify if this is ralink sta */
1673 /* Customer proprietary IE */
1675 /* get a unique AID */
1676 if (pstat->aid > 0) {
1677 DBG_8723A(" old AID %d\n", pstat->aid);
1679 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1680 if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1683 if (pstat->aid > NUM_STA)
1684 pstat->aid = NUM_STA;
1685 if (pstat->aid > pstapriv->max_num_sta) {
1689 DBG_8723A(" no room for more AIDs\n");
1691 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1693 goto OnAssocReq23aFail;
1695 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1696 DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
1700 pstat->state &= ~WIFI_FW_ASSOC_STATE;
1701 pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1703 spin_lock_bh(&pstapriv->auth_list_lock);
1704 if (!list_empty(&pstat->auth_list)) {
1705 list_del_init(&pstat->auth_list);
1706 pstapriv->auth_list_cnt--;
1708 spin_unlock_bh(&pstapriv->auth_list_lock);
1710 spin_lock_bh(&pstapriv->asoc_list_lock);
1711 if (list_empty(&pstat->asoc_list)) {
1712 pstat->expire_to = pstapriv->expire_to;
1713 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1714 pstapriv->asoc_list_cnt++;
1716 spin_unlock_bh(&pstapriv->asoc_list_lock);
1718 /* now the station is qualified to join our BSS... */
1719 if (pstat && pstat->state & WIFI_FW_ASSOC_SUCCESS &&
1720 status == WLAN_STATUS_SUCCESS) {
1721 #ifdef CONFIG_8723AU_AP_MODE
1722 /* 1 bss_cap_update & sta_info_update23a */
1723 bss_cap_update_on_sta_join23a(padapter, pstat);
1724 sta_info_update23a(padapter, pstat);
1726 /* issue assoc rsp before notify station join event. */
1727 if (ieee80211_is_assoc_req(mgmt->frame_control))
1728 issue_assocrsp(padapter, status, pstat,
1729 IEEE80211_STYPE_ASSOC_RESP);
1731 issue_assocrsp(padapter, status, pstat,
1732 IEEE80211_STYPE_REASSOC_RESP);
1734 /* 2 - report to upper layer */
1735 DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
1736 rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1738 /* 3-(1) report sta add event */
1739 report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid);
1747 #ifdef CONFIG_8723AU_AP_MODE
1748 issue_deauth23a(padapter, mgmt->sa, status);
1754 #ifdef CONFIG_8723AU_AP_MODE
1756 if (ieee80211_is_assoc_req(mgmt->frame_control))
1757 issue_assocrsp(padapter, status, pstat,
1758 IEEE80211_STYPE_ASSOC_RESP);
1760 issue_assocrsp(padapter, status, pstat,
1761 IEEE80211_STYPE_REASSOC_RESP);
1764 #endif /* CONFIG_8723AU_AP_MODE */
1770 OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1772 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1773 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1774 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1775 struct sk_buff *skb = precv_frame->pkt;
1776 struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
1778 unsigned short status;
1780 u8 *pframe = skb->data;
1781 int pkt_len = skb->len;
1784 DBG_8723A("%s\n", __func__);
1786 /* check A1 matches or not */
1787 if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da))
1790 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1793 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1796 del_timer_sync(&pmlmeext->link_timer);
1799 status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
1801 DBG_8723A("assoc reject, status code: %d\n", status);
1802 pmlmeinfo->state = MSR_NOLINK;
1804 goto report_assoc_result;
1807 /* get capabilities */
1808 pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info);
1811 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
1814 res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
1816 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1818 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1820 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
1821 pmgmt->u.assoc_resp.variable, pielen);
1823 HT_caps_handler23a(padapter, p);
1825 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
1826 pmgmt->u.assoc_resp.variable, pielen);
1828 HT_info_handler23a(padapter, p);
1830 p = cfg80211_find_ie(WLAN_EID_ERP_INFO,
1831 pmgmt->u.assoc_resp.variable, pielen);
1833 ERP_IE_handler23a(padapter, p);
1835 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1837 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1838 WLAN_OUI_TYPE_MICROSOFT_WMM,
1839 pie, pframe + pkt_len - pie);
1844 /* if this IE is too short, try the next */
1847 /* if this IE is WMM params, we found what we wanted */
1853 WMM_param_handler23a(padapter, p);
1855 pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
1856 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1858 /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1859 UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates);
1861 report_assoc_result:
1862 pmlmepriv->assoc_rsp_len = 0;
1864 kfree(pmlmepriv->assoc_rsp);
1865 pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC);
1866 if (pmlmepriv->assoc_rsp) {
1867 memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len);
1868 pmlmepriv->assoc_rsp_len = pkt_len;
1871 kfree(pmlmepriv->assoc_rsp);
1873 report_join_res23a(padapter, res);
1879 OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1881 unsigned short reason;
1882 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1883 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1884 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1885 struct sk_buff *skb = precv_frame->pkt;
1886 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1888 if (!ether_addr_equal(mgmt->bssid,
1889 get_my_bssid23a(&pmlmeinfo->network)))
1892 reason = le16_to_cpu(mgmt->u.deauth.reason_code);
1894 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1896 #ifdef CONFIG_8723AU_AP_MODE
1897 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1898 struct sta_info *psta;
1899 struct sta_priv *pstapriv = &padapter->stapriv;
1901 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
1902 "sta:%pM\n", reason, mgmt->sa);
1904 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1908 spin_lock_bh(&pstapriv->asoc_list_lock);
1909 if (!list_empty(&psta->asoc_list)) {
1910 list_del_init(&psta->asoc_list);
1911 pstapriv->asoc_list_cnt--;
1912 updated = ap_free_sta23a(padapter, psta,
1915 spin_unlock_bh(&pstapriv->asoc_list_lock);
1917 associated_clients_update23a(padapter, updated);
1924 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
1925 "sta:%pM\n", reason, mgmt->bssid);
1927 receive_disconnect23a(padapter, mgmt->bssid, reason);
1929 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1935 OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1937 unsigned short reason;
1938 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1939 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1940 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1941 struct sk_buff *skb = precv_frame->pkt;
1942 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1944 if (!ether_addr_equal(mgmt->bssid,
1945 get_my_bssid23a(&pmlmeinfo->network)))
1948 reason = le16_to_cpu(mgmt->u.disassoc.reason_code);
1950 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1952 #ifdef CONFIG_8723AU_AP_MODE
1953 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1954 struct sta_info *psta;
1955 struct sta_priv *pstapriv = &padapter->stapriv;
1957 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
1958 " sta:%pM\n", reason, mgmt->sa);
1960 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1964 spin_lock_bh(&pstapriv->asoc_list_lock);
1965 if (!list_empty(&psta->asoc_list)) {
1966 list_del_init(&psta->asoc_list);
1967 pstapriv->asoc_list_cnt--;
1968 updated = ap_free_sta23a(padapter, psta,
1971 spin_unlock_bh(&pstapriv->asoc_list_lock);
1973 associated_clients_update23a(padapter, updated);
1980 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
1981 "code(%d) sta:%pM\n", reason, mgmt->bssid);
1983 receive_disconnect23a(padapter, mgmt->bssid, reason);
1985 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1990 OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1992 DBG_8723A("%s\n", __func__);
1997 on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2003 OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2009 OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2014 static int OnAction23a_back23a(struct rtw_adapter *padapter,
2015 struct recv_frame *precv_frame)
2018 struct sta_info *psta = NULL;
2019 struct recv_reorder_ctrl *preorder_ctrl;
2020 unsigned char category, action;
2021 unsigned short tid, status, capab, params, reason_code = 0;
2022 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2023 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2024 struct sk_buff *skb = precv_frame->pkt;
2025 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2026 struct sta_priv *pstapriv = &padapter->stapriv;
2028 /* check RA matches or not */
2029 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
2032 DBG_8723A("%s\n", __func__);
2034 if ((pmlmeinfo->state&0x03) != MSR_AP)
2035 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2039 psta = rtw_get_stainfo23a(pstapriv, addr);
2044 category = mgmt->u.action.category;
2045 if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */
2046 if (!pmlmeinfo->HT_enable)
2048 /* action_code is located in the same place for all
2049 action events, so pick any */
2050 action = mgmt->u.action.u.wme_action.action_code;
2051 DBG_8723A("%s, action =%d\n", __func__, action);
2053 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
2054 memcpy(&pmlmeinfo->ADDBA_req,
2055 &mgmt->u.action.u.addba_req.dialog_token,
2056 sizeof(struct ADDBA_request));
2057 process_addba_req23a(padapter,
2058 (u8 *)&pmlmeinfo->ADDBA_req, addr);
2059 if (pmlmeinfo->bAcceptAddbaReq == true)
2060 issue_action_BA23a(padapter, addr,
2061 WLAN_ACTION_ADDBA_RESP, 0);
2063 /* reject ADDBA Req */
2064 issue_action_BA23a(padapter, addr,
2065 WLAN_ACTION_ADDBA_RESP, 37);
2068 case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
2069 status = get_unaligned_le16(
2070 &mgmt->u.action.u.addba_resp.status);
2071 capab = get_unaligned_le16(
2072 &mgmt->u.action.u.addba_resp.capab);
2073 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
2074 if (status == 0) { /* successful */
2075 DBG_8723A("agg_enable for TID =%d\n", tid);
2076 psta->htpriv.agg_enable_bitmap |= BIT(tid);
2077 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2079 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2082 case WLAN_ACTION_DELBA: /* DELBA */
2083 params = get_unaligned_le16(
2084 &mgmt->u.action.u.delba.params);
2087 if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
2088 preorder_ctrl = &psta->recvreorder_ctrl[tid];
2089 preorder_ctrl->enable = false;
2090 preorder_ctrl->indicate_seq = 0xffff;
2092 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2093 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2095 reason_code = get_unaligned_le16(
2096 &mgmt->u.action.u.delba.reason_code);
2097 /* todo: how to notify the host while receiving
2107 static int on_action_public23a(struct rtw_adapter *padapter,
2108 struct recv_frame *precv_frame)
2110 struct sk_buff *skb = precv_frame->pkt;
2111 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2112 u8 *pframe = skb->data;
2115 /* check RA matches or not */
2116 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
2119 channel = rtw_get_oper_ch23a(padapter);
2121 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2122 freq = ieee80211_channel_to_frequency(channel,
2123 IEEE80211_BAND_2GHZ);
2125 freq = ieee80211_channel_to_frequency(channel,
2126 IEEE80211_BAND_5GHZ);
2128 if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
2136 OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2142 OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2148 OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2154 OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2158 struct action_handler *ptable;
2159 struct sk_buff *skb = precv_frame->pkt;
2160 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2162 category = mgmt->u.action.category;
2165 i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) {
2166 ptable = &OnAction23a_tbl[i];
2168 if (category == ptable->num)
2169 ptable->func(padapter, precv_frame);
2175 static int DoReserved23a(struct rtw_adapter *padapter,
2176 struct recv_frame *precv_frame)
2181 struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
2183 struct xmit_frame *pmgntframe;
2184 struct xmit_buf *pxmitbuf;
2186 pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
2189 DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__,
2190 pxmitpriv->adapter->pnetdev->name);
2194 pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
2196 DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__,
2197 pxmitpriv->adapter->pnetdev->name);
2198 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
2203 pmgntframe->frame_tag = MGNT_FRAMETAG;
2204 pmgntframe->pxmitbuf = pxmitbuf;
2205 pmgntframe->buf_addr = pxmitbuf->pbuf;
2206 pxmitbuf->priv_data = pmgntframe;
2212 /****************************************************************************
2214 Following are some TX functions for WiFi MLME
2216 *****************************************************************************/
2218 void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
2220 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2222 pmlmeext->tx_rate = rate;
2223 DBG_8723A("%s(): rate = %x\n", __func__, rate);
2226 void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
2227 struct pkt_attrib *pattrib)
2229 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2231 memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
2233 pattrib->hdrlen = 24;
2234 pattrib->nr_frags = 1;
2235 pattrib->priority = 7;
2236 pattrib->mac_id = 0;
2237 pattrib->qsel = 0x12;
2239 pattrib->pktlen = 0;
2241 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
2242 pattrib->raid = 6;/* b mode */
2244 pattrib->raid = 5;/* a/g mode */
2246 pattrib->encrypt = 0;
2247 pattrib->bswenc = false;
2249 pattrib->qos_en = false;
2250 pattrib->ht_en = false;
2251 pattrib->bwmode = HT_CHANNEL_WIDTH_20;
2252 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2253 pattrib->sgi = false;
2255 pattrib->seqnum = pmlmeext->mgnt_seq;
2257 pattrib->retry_ctrl = true;
2260 void dump_mgntframe23a(struct rtw_adapter *padapter,
2261 struct xmit_frame *pmgntframe)
2263 if (padapter->bSurpriseRemoved == true ||
2264 padapter->bDriverStopped == true)
2267 rtl8723au_mgnt_xmit(padapter, pmgntframe);
2270 int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
2271 struct xmit_frame *pmgntframe, int timeout_ms)
2275 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2276 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2277 struct submit_ctx sctx;
2279 if (padapter->bSurpriseRemoved == true ||
2280 padapter->bDriverStopped == true)
2283 rtw_sctx_init23a(&sctx, timeout_ms);
2284 pxmitbuf->sctx = &sctx;
2286 ret = rtl8723au_mgnt_xmit(padapter, pmgntframe);
2288 if (ret == _SUCCESS)
2289 ret = rtw_sctx_wait23a(&sctx);
2291 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2292 pxmitbuf->sctx = NULL;
2293 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2298 int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
2299 struct xmit_frame *pmgntframe)
2302 u32 timeout_ms = 500;/* 500ms */
2303 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2305 if (padapter->bSurpriseRemoved == true ||
2306 padapter->bDriverStopped == true)
2309 mutex_lock(&pxmitpriv->ack_tx_mutex);
2310 pxmitpriv->ack_tx = true;
2312 pmgntframe->ack_report = 1;
2313 if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2314 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
2316 pxmitpriv->ack_tx = false;
2317 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2322 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2330 ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
2332 /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n",
2333 __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
2335 if (ssid_ie && ssid_len_ori > 0) {
2336 switch (hidden_ssid_mode) {
2338 next_ie = ssid_ie + 2 + ssid_len_ori;
2339 remain_len = ies_len -(next_ie-ies);
2342 memcpy(ssid_ie+2, next_ie, remain_len);
2343 len_diff -= ssid_len_ori;
2347 memset(&ssid_ie[2], 0, ssid_len_ori);
2357 void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
2359 struct xmit_frame *pmgntframe;
2360 struct pkt_attrib *pattrib;
2361 unsigned char *pframe;
2362 struct ieee80211_mgmt *mgmt;
2363 unsigned int rate_len;
2364 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2365 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2366 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2367 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2368 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2369 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2374 /* DBG_8723A("%s\n", __func__); */
2376 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2378 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2381 #ifdef CONFIG_8723AU_AP_MODE
2382 spin_lock_bh(&pmlmepriv->bcn_update_lock);
2385 /* update attribute */
2386 pattrib = &pmgntframe->attrib;
2387 update_mgntframe_attrib23a(padapter, pattrib);
2388 pattrib->qsel = 0x10;
2390 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2392 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2393 mgmt = (struct ieee80211_mgmt *)pframe;
2395 mgmt->frame_control =
2396 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
2399 ether_addr_copy(mgmt->da, bc_addr);
2400 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2401 ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
2403 /* timestamp will be inserted by hardware */
2405 put_unaligned_le16(cur_network->beacon_interval,
2406 &mgmt->u.beacon.beacon_int);
2408 put_unaligned_le16(cur_network->capability,
2409 &mgmt->u.beacon.capab_info);
2411 pframe = mgmt->u.beacon.variable;
2412 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
2414 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2417 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
2418 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2419 len_diff = update_hidden_ssid(pframe, cur_network->IELength,
2420 pmlmeinfo->hidden_ssid_mode);
2421 pframe += (cur_network->IELength+len_diff);
2422 pattrib->pktlen += (cur_network->IELength+len_diff);
2424 iebuf = mgmt->u.beacon.variable;
2425 buflen = pattrib->pktlen -
2426 offsetof(struct ieee80211_mgmt, u.beacon.variable);
2427 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2428 WLAN_OUI_TYPE_MICROSOFT_WPS,
2431 if (wps_ie && wps_ie[1] > 0) {
2432 rtw_get_wps_attr_content23a(wps_ie, wps_ie[1],
2433 WPS_ATTR_SELECTED_REGISTRAR,
2437 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2439 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2445 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2446 cur_network->Ssid.ssid_len,
2447 cur_network->Ssid.ssid, &pattrib->pktlen);
2449 /* supported rates... */
2450 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2451 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2452 ((rate_len > 8)? 8: rate_len),
2453 cur_network->SupportedRates, &pattrib->pktlen);
2455 /* DS parameter set */
2456 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
2457 &cur_network->DSConfig, &pattrib->pktlen);
2459 /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */
2463 /* IBSS Parameter Set... */
2464 /* ATIMWindow = cur->ATIMWindow; */
2466 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2467 (unsigned char *)&ATIMWindow,
2471 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2472 &erpinfo, &pattrib->pktlen);
2475 /* EXTERNDED SUPPORTED RATE */
2477 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2479 cur_network->SupportedRates + 8,
2482 /* todo:HT for adhoc */
2486 #ifdef CONFIG_8723AU_AP_MODE
2487 pmlmepriv->update_bcn = false;
2489 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2492 if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
2493 DBG_8723A("beacon frame too large\n");
2497 pattrib->last_txcmdsz = pattrib->pktlen;
2499 /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
2501 dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
2503 dump_mgntframe23a(padapter, pmgntframe);
2506 static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da,
2507 u8 is_valid_p2p_probereq)
2509 struct xmit_frame *pmgntframe;
2510 struct pkt_attrib *pattrib;
2511 unsigned char *pframe;
2512 struct ieee80211_mgmt *mgmt;
2513 unsigned char *mac, *bssid;
2514 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2515 #ifdef CONFIG_8723AU_AP_MODE
2519 int ssid_ielen_diff;
2522 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2523 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2524 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2525 unsigned int rate_len;
2527 /* DBG_8723A("%s\n", __func__); */
2529 if (cur_network->IELength > MAX_IE_SZ)
2532 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2534 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2538 /* update attribute */
2539 pattrib = &pmgntframe->attrib;
2540 update_mgntframe_attrib23a(padapter, pattrib);
2542 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2544 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
2545 mgmt = (struct ieee80211_mgmt *)pframe;
2547 mac = myid(&padapter->eeprompriv);
2548 bssid = cur_network->MacAddress;
2550 mgmt->frame_control =
2551 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
2553 ether_addr_copy(mgmt->da, da);
2554 ether_addr_copy(mgmt->sa, mac);
2555 ether_addr_copy(mgmt->bssid, bssid);
2557 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2558 pmlmeext->mgnt_seq++;
2560 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2562 /* timestamp will be inserted by hardware */
2563 put_unaligned_le16(cur_network->beacon_interval,
2564 &mgmt->u.probe_resp.beacon_int);
2566 put_unaligned_le16(cur_network->capability,
2567 &mgmt->u.probe_resp.capab_info);
2569 pframe = mgmt->u.probe_resp.variable;
2571 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
2573 /* below for ad-hoc mode */
2575 #ifdef CONFIG_8723AU_AP_MODE
2576 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2577 pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2578 WLAN_OUI_TYPE_MICROSOFT_WPS,
2580 cur_network->IELength);
2582 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2583 pframe += cur_network->IELength;
2584 pattrib->pktlen += cur_network->IELength;
2586 /* retrieve SSID IE from cur_network->Ssid */
2588 ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable,
2589 WLAN_EID_SSID, &ssid_ielen,
2590 pframe - mgmt->u.probe_resp.variable);
2592 ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
2594 if (ssid_ie && cur_network->Ssid.ssid_len) {
2595 uint remainder_ielen;
2598 remainder_ie = ssid_ie + 2;
2600 remainder_ielen = pframe - remainder_ie;
2602 DBG_8723A_LEVEL(_drv_warning_, "%s(%s): "
2603 "remainder_ielen > MAX_IE_SZ\n",
2604 __func__, padapter->pnetdev->name);
2605 if (remainder_ielen > MAX_IE_SZ)
2606 remainder_ielen = MAX_IE_SZ;
2608 memcpy(buf, remainder_ie, remainder_ielen);
2609 memcpy(remainder_ie + ssid_ielen_diff, buf,
2611 *(ssid_ie + 1) = cur_network->Ssid.ssid_len;
2612 memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
2613 cur_network->Ssid.ssid_len);
2615 pframe += ssid_ielen_diff;
2616 pattrib->pktlen += ssid_ielen_diff;
2622 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2623 cur_network->Ssid.ssid_len,
2624 cur_network->Ssid.ssid,
2627 /* supported rates... */
2628 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2629 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2630 ((rate_len > 8)? 8: rate_len),
2631 cur_network->SupportedRates,
2634 /* DS parameter set */
2635 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
2636 (unsigned char *)&cur_network->DSConfig,
2639 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
2642 /* IBSS Parameter Set... */
2643 /* ATIMWindow = cur->ATIMWindow; */
2645 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2646 (unsigned char *)&ATIMWindow,
2650 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2651 &erpinfo, &pattrib->pktlen);
2654 /* EXTERNDED SUPPORTED RATE */
2656 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2658 cur_network->SupportedRates + 8,
2661 /* todo:HT for adhoc */
2664 pattrib->last_txcmdsz = pattrib->pktlen;
2666 dump_mgntframe23a(padapter, pmgntframe);
2671 static int _issue_probereq(struct rtw_adapter *padapter,
2672 struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
2675 struct xmit_frame *pmgntframe;
2676 struct pkt_attrib *pattrib;
2677 unsigned char *pframe;
2678 struct ieee80211_hdr *pwlanhdr;
2680 unsigned char bssrate[NumRates];
2681 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2682 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2683 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2684 int bssrate_len = 0;
2685 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2687 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2690 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2694 /* update attribute */
2695 pattrib = &pmgntframe->attrib;
2696 update_mgntframe_attrib23a(padapter, pattrib);
2698 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2700 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2701 pwlanhdr = (struct ieee80211_hdr *)pframe;
2703 mac = myid(&padapter->eeprompriv);
2705 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2706 IEEE80211_STYPE_PROBE_REQ);
2709 /* unicast probe request frame */
2710 ether_addr_copy(pwlanhdr->addr1, da);
2711 ether_addr_copy(pwlanhdr->addr3, da);
2713 /* broadcast probe request frame */
2714 ether_addr_copy(pwlanhdr->addr1, bc_addr);
2715 ether_addr_copy(pwlanhdr->addr3, bc_addr);
2718 ether_addr_copy(pwlanhdr->addr2, mac);
2720 pwlanhdr->seq_ctrl =
2721 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2723 pmlmeext->mgnt_seq++;
2725 pframe += sizeof (struct ieee80211_hdr_3addr);
2726 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
2729 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
2730 pssid->ssid, &pattrib->pktlen);
2732 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
2735 get_rate_set23a(padapter, bssrate, &bssrate_len);
2737 if (bssrate_len > 8) {
2738 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
2739 bssrate, &pattrib->pktlen);
2740 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2741 (bssrate_len - 8), (bssrate + 8),
2744 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2745 bssrate_len, bssrate, &pattrib->pktlen);
2748 /* add wps_ie for wps2.0 */
2749 if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
2750 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
2751 pmlmepriv->wps_probe_req_ie_len);
2752 pframe += pmlmepriv->wps_probe_req_ie_len;
2753 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2756 pattrib->last_txcmdsz = pattrib->pktlen;
2758 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2759 "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz);
2762 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
2764 dump_mgntframe23a(padapter, pmgntframe);
2772 static inline void issue_probereq(struct rtw_adapter *padapter,
2773 struct cfg80211_ssid *pssid, u8 *da)
2775 _issue_probereq(padapter, pssid, da, false);
2778 static int issue_probereq_ex(struct rtw_adapter *padapter,
2779 struct cfg80211_ssid *pssid, u8 *da,
2780 int try_cnt, int wait_ms)
2784 unsigned long start = jiffies;
2787 ret = _issue_probereq(padapter, pssid, da,
2788 wait_ms > 0 ? true : false);
2792 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2795 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2798 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2805 if (try_cnt && wait_ms) {
2807 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
2808 __func__, padapter->pnetdev->name,
2809 da, rtw_get_oper_ch23a(padapter),
2810 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2811 jiffies_to_msecs(jiffies - start));
2813 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
2814 __func__, padapter->pnetdev->name,
2815 rtw_get_oper_ch23a(padapter),
2816 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2817 jiffies_to_msecs(jiffies - start));
2823 /* if psta == NULL, indiate we are station(client) now... */
2824 static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
2825 unsigned short status)
2827 struct xmit_frame *pmgntframe;
2828 struct pkt_attrib *pattrib;
2829 unsigned char *pframe;
2830 struct ieee80211_mgmt *mgmt;
2833 int use_shared_key = 0;
2834 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2835 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2836 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2838 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2842 /* update attribute */
2843 pattrib = &pmgntframe->attrib;
2844 update_mgntframe_attrib23a(padapter, pattrib);
2846 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2848 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2849 mgmt = (struct ieee80211_mgmt *)pframe;
2851 mgmt->frame_control =
2852 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
2853 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2854 pmlmeext->mgnt_seq++;
2856 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable);
2858 if (psta) { /* for AP mode */
2859 #ifdef CONFIG_8723AU_AP_MODE
2860 unsigned short val16;
2862 ether_addr_copy(mgmt->da, psta->hwaddr);
2863 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2864 ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv));
2866 /* setting auth algo number */
2867 val16 = (u16)psta->authalg;
2869 if (status != WLAN_STATUS_SUCCESS)
2875 mgmt->u.auth.auth_alg = cpu_to_le16(val16);
2877 /* setting auth seq number */
2878 mgmt->u.auth.auth_transaction =
2879 cpu_to_le16((u16)psta->auth_seq);
2881 /* setting status code... */
2882 mgmt->u.auth.status_code = cpu_to_le16(status);
2884 pframe = mgmt->u.auth.variable;
2885 /* added challenging text... */
2886 if ((psta->auth_seq == 2) &&
2887 (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
2888 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2889 psta->chg_txt, &pattrib->pktlen);
2892 struct ieee80211_mgmt *iv_mgmt;
2894 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
2895 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2896 ether_addr_copy(mgmt->bssid,
2897 get_my_bssid23a(&pmlmeinfo->network));
2899 /* setting auth algo number */
2900 /* 0:OPEN System, 1:Shared key */
2901 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
2903 auth_algo = WLAN_AUTH_SHARED_KEY;
2905 auth_algo = WLAN_AUTH_OPEN;
2907 /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
2908 (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
2909 pmlmeinfo->auth_seq); */
2911 /* setting IV for auth seq #3 */
2912 if ((pmlmeinfo->auth_seq == 3) &&
2913 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2914 (use_shared_key == 1)) {
2915 u32 *piv = (u32 *)&mgmt->u.auth;
2917 iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4);
2918 /* DBG_8723A("==> iv(%d), key_index(%d)\n",
2919 pmlmeinfo->iv, pmlmeinfo->key_index); */
2920 val32 = (pmlmeinfo->iv & 0x3fffffff) |
2921 (pmlmeinfo->key_index << 30);
2923 put_unaligned_le32(val32, piv);
2925 pattrib->pktlen += 4;
2927 pattrib->iv_len = IEEE80211_WEP_IV_LEN;
2931 iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo);
2933 /* setting auth seq number */
2934 iv_mgmt->u.auth.auth_transaction =
2935 cpu_to_le16(pmlmeinfo->auth_seq);
2937 /* setting status code... */
2938 iv_mgmt->u.auth.status_code = cpu_to_le16(status);
2940 pframe = iv_mgmt->u.auth.variable;
2942 /* then checking to see if sending challenging text... */
2943 if ((pmlmeinfo->auth_seq == 3) &&
2944 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2945 (use_shared_key == 1)) {
2946 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2950 mgmt->frame_control |=
2951 cpu_to_le16(IEEE80211_FCTL_PROTECTED);
2953 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2955 pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40;
2957 pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
2959 pattrib->pktlen += pattrib->icv_len;
2963 pattrib->last_txcmdsz = pattrib->pktlen;
2965 rtw_wep_encrypt23a(padapter, pmgntframe);
2966 DBG_8723A("%s\n", __func__);
2967 dump_mgntframe23a(padapter, pmgntframe);
2972 #ifdef CONFIG_8723AU_AP_MODE
2973 static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
2974 struct sta_info *pstat, u16 pkt_type)
2976 struct xmit_frame *pmgntframe;
2977 struct ieee80211_mgmt *mgmt;
2978 struct pkt_attrib *pattrib;
2979 unsigned char *pframe;
2980 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2981 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2982 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2983 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2984 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
2986 u8 *ie = pnetwork->IEs;
2988 DBG_8723A("%s\n", __func__);
2990 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2994 /* update attribute */
2995 pattrib = &pmgntframe->attrib;
2996 update_mgntframe_attrib23a(padapter, pattrib);
2998 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3000 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3001 mgmt = (struct ieee80211_mgmt *)pframe;
3003 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
3005 ether_addr_copy(mgmt->da, pstat->hwaddr);
3006 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3007 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3009 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3011 pmlmeext->mgnt_seq++;
3013 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3015 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
3017 mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability);
3018 mgmt->u.assoc_resp.status_code = cpu_to_le16(status);
3019 mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
3021 pframe = mgmt->u.assoc_resp.variable;
3023 if (pstat->bssratelen <= 8) {
3024 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3025 pstat->bssratelen, pstat->bssrateset,
3028 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3029 pstat->bssrateset, &pattrib->pktlen);
3030 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3031 pstat->bssratelen - 8,
3032 pstat->bssrateset + 8, &pattrib->pktlen);
3035 if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
3036 /* FILL HT CAP INFO IE */
3037 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
3038 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie,
3039 pnetwork->IELength);
3041 memcpy(pframe, p, p[1] + 2);
3042 pframe += (p[1] + 2);
3043 pattrib->pktlen += (p[1] + 2);
3046 /* FILL HT ADD INFO IE */
3047 /* p = hostapd_eid_ht_operation(hapd, p); */
3048 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie,
3049 pnetwork->IELength);
3050 if (p && p[1] > 0) {
3051 memcpy(pframe, p, p[1] + 2);
3052 pframe += (p[1] + 2);
3053 pattrib->pktlen += (p[1] + 2);
3058 if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) {
3059 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
3063 for (p = ie; ; p += (ie_len + 2)) {
3064 p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
3065 pnetwork->IELength - (ie_len + 2));
3070 if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) {
3071 memcpy(pframe, p, ie_len + 2);
3072 pframe += (ie_len + 2);
3073 pattrib->pktlen += (ie_len + 2);
3078 if (!p || ie_len == 0)
3083 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
3084 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3085 REALTEK_96B_IE, &pattrib->pktlen);
3088 pattrib->last_txcmdsz = pattrib->pktlen;
3090 dump_mgntframe23a(padapter, pmgntframe);
3094 static void issue_assocreq(struct rtw_adapter *padapter)
3097 struct xmit_frame *pmgntframe;
3098 struct pkt_attrib *pattrib;
3099 unsigned char *pframe;
3101 struct ieee80211_mgmt *mgmt;
3102 unsigned int i, j, index = 0;
3103 unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
3104 struct registry_priv *pregpriv = &padapter->registrypriv;
3105 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3106 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3107 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3108 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3109 int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
3112 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3116 /* update attribute */
3117 pattrib = &pmgntframe->attrib;
3118 update_mgntframe_attrib23a(padapter, pattrib);
3120 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3122 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
3123 mgmt = (struct ieee80211_mgmt *)pframe;
3125 mgmt->frame_control =
3126 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ);
3128 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
3129 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3130 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3132 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3133 pmlmeext->mgnt_seq++;
3136 put_unaligned_le16(pmlmeinfo->network.capability,
3137 &mgmt->u.assoc_req.capab_info);
3138 /* todo: listen interval for power saving */
3139 put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval);
3141 pframe = mgmt->u.assoc_req.variable;
3142 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
3145 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
3146 pmlmeinfo->network.Ssid.ssid_len,
3147 pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
3149 /* supported rate & extended supported rate */
3151 get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
3152 /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */
3154 /* for JAPAN, channel 14 can only uses B Mode(CCK) */
3155 if (pmlmeext->cur_channel == 14)
3156 sta_bssrate_len = 4;
3158 /* for (i = 0; i < sta_bssrate_len; i++) { */
3159 /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
3162 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3163 if (pmlmeinfo->network.SupportedRates[i] == 0)
3165 DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
3166 pmlmeinfo->network.SupportedRates[i]);
3169 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3170 if (pmlmeinfo->network.SupportedRates[i] == 0)
3173 /* Check if the AP's supported rates are also
3174 supported by STA. */
3175 for (j = 0; j < sta_bssrate_len; j++) {
3176 /* Avoid the proprietary data rate (22Mbps) of
3177 Handlink WSG-4000 AP */
3178 if ((pmlmeinfo->network.SupportedRates[i] |
3179 IEEE80211_BASIC_RATE_MASK) ==
3180 (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
3181 /* DBG_8723A("match i = %d, j =%d\n", i, j); */
3186 if (j == sta_bssrate_len) {
3187 /* the rate is not supported by STA */
3188 DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
3189 "STA!\n", __func__, i,
3190 pmlmeinfo->network.SupportedRates[i]);
3192 /* the rate is supported by STA */
3193 bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
3197 bssrate_len = index;
3198 DBG_8723A("bssrate_len = %d\n", bssrate_len);
3200 if (bssrate_len == 0) {
3201 rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
3202 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
3203 goto exit; /* don't connect to AP if no joint supported rate */
3206 if (bssrate_len > 8) {
3207 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3208 bssrate, &pattrib->pktlen);
3209 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3210 (bssrate_len - 8), (bssrate + 8),
3213 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3214 bssrate_len, bssrate, &pattrib->pktlen);
3218 pie = pmlmeinfo->network.IEs;
3219 pie_len = pmlmeinfo->network.IELength;
3221 p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
3223 pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
3227 if (padapter->mlmepriv.htpriv.ht_option) {
3228 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
3230 if (p && !is_ap_in_tkip23a(padapter)) {
3231 struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap;
3233 memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap));
3235 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
3236 if (pregpriv->cbw40_enable == 0) {
3237 cap->cap_info &= ~cpu_to_le16(
3238 IEEE80211_HT_CAP_SGI_40 |
3239 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3241 cap->cap_info |= cpu_to_le16(
3242 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3245 /* todo: disable SM power save mode */
3246 cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
3248 rf_type = rtl8723a_get_rf_type(padapter);
3249 /* switch (pregpriv->rf_config) */
3252 /* RX STBC One spatial stream */
3253 if (pregpriv->rx_stbc)
3254 cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3256 memcpy(&cap->mcs, MCS_rate_1R23A, 16);
3262 /* enable for 2.4/5 GHz */
3263 if (pregpriv->rx_stbc == 0x3 ||
3264 (pmlmeext->cur_wireless_mode &
3266 /* enable for 2.4GHz */
3267 pregpriv->rx_stbc == 0x1) ||
3268 (pmlmeext->cur_wireless_mode &
3270 pregpriv->rx_stbc == 0x2) ||
3271 /* enable for 5GHz */
3272 pregpriv->wifi_spec == 1) {
3273 DBG_8723A("declare supporting RX "
3275 /* RX STBC two spatial stream */
3276 cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3278 memcpy(&cap->mcs, MCS_rate_2R23A, 16);
3282 if (rtl8723a_BT_coexist(padapter) &&
3283 rtl8723a_BT_using_antenna_1(padapter)) {
3285 cap->ampdu_params_info &=
3286 ~IEEE80211_HT_AMPDU_PARM_FACTOR;
3287 /* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */
3290 pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
3291 p[1], (u8 *)&pmlmeinfo->ht_cap,
3296 /* vendor specific IE, such as WPA, WMM, WPS */
3297 for (i = 0; i < pmlmeinfo->network.IELength;) {
3298 p = pmlmeinfo->network.IEs + i;
3301 case WLAN_EID_VENDOR_SPECIFIC:
3302 if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) ||
3303 !memcmp(p + 2, WMM_OUI23A, 4) ||
3304 !memcmp(p + 2, WPS_OUI23A, 4)) {
3307 if (!padapter->registrypriv.wifi_spec) {
3308 /* Commented by Kurt 20110629 */
3309 /* In some older APs, WPS handshake */
3310 /* would be fail if we append vender
3311 extensions informations to AP */
3312 if (!memcmp(p + 2, WPS_OUI23A, 4))
3315 pframe = rtw_set_ie23a(pframe,
3316 WLAN_EID_VENDOR_SPECIFIC,
3329 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3330 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3331 REALTEK_96B_IE, &pattrib->pktlen);
3333 pattrib->last_txcmdsz = pattrib->pktlen;
3334 dump_mgntframe23a(padapter, pmgntframe);
3339 pmlmepriv->assoc_req_len = 0;
3340 if (ret == _SUCCESS) {
3341 kfree(pmlmepriv->assoc_req);
3342 pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
3343 if (pmlmepriv->assoc_req) {
3344 memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen);
3345 pmlmepriv->assoc_req_len = pattrib->pktlen;
3348 kfree(pmlmepriv->assoc_req);
3353 /* when wait_ack is true, this function should be called at process context */
3354 static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3355 unsigned int power_mode, int wait_ack)
3358 struct xmit_frame *pmgntframe;
3359 struct pkt_attrib *pattrib;
3360 unsigned char *pframe;
3361 struct ieee80211_hdr *pwlanhdr;
3362 struct xmit_priv *pxmitpriv;
3363 struct mlme_ext_priv *pmlmeext;
3364 struct mlme_ext_info *pmlmeinfo;
3366 /* DBG_8723A("%s:%d\n", __func__, power_mode); */
3371 pxmitpriv = &padapter->xmitpriv;
3372 pmlmeext = &padapter->mlmeextpriv;
3373 pmlmeinfo = &pmlmeext->mlmext_info;
3375 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3379 /* update attribute */
3380 pattrib = &pmgntframe->attrib;
3381 update_mgntframe_attrib23a(padapter, pattrib);
3382 pattrib->retry_ctrl = false;
3384 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3386 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3387 pwlanhdr = (struct ieee80211_hdr *)pframe;
3389 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3390 IEEE80211_STYPE_NULLFUNC);
3392 if ((pmlmeinfo->state&0x03) == MSR_AP)
3393 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3394 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3395 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3398 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
3400 ether_addr_copy(pwlanhdr->addr1, da);
3401 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3402 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3404 pwlanhdr->seq_ctrl =
3405 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3406 pmlmeext->mgnt_seq++;
3408 pframe += sizeof(struct ieee80211_hdr_3addr);
3409 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3411 pattrib->last_txcmdsz = pattrib->pktlen;
3414 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3416 dump_mgntframe23a(padapter, pmgntframe);
3424 /* when wait_ms >0 , this function should be called at process context */
3425 /* da == NULL for station mode */
3426 int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3427 unsigned int power_mode, int try_cnt, int wait_ms)
3431 unsigned long start = jiffies;
3432 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3433 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3435 /* da == NULL, assume it's null data for sta to ap*/
3437 da = get_my_bssid23a(&pmlmeinfo->network);
3440 ret = _issue_nulldata23a(padapter, da, power_mode,
3441 wait_ms > 0 ? true : false);
3445 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3448 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3451 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3458 if (try_cnt && wait_ms) {
3460 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3461 __func__, padapter->pnetdev->name,
3462 da, rtw_get_oper_ch23a(padapter),
3463 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3464 jiffies_to_msecs(jiffies - start));
3466 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3467 __func__, padapter->pnetdev->name,
3468 rtw_get_oper_ch23a(padapter),
3469 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3470 jiffies_to_msecs(jiffies - start));
3476 /* when wait_ack is true, this function should be called at process context */
3477 static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
3478 unsigned char *da, u16 tid, int wait_ack)
3481 struct xmit_frame *pmgntframe;
3482 struct pkt_attrib *pattrib;
3483 unsigned char *pframe;
3484 struct ieee80211_qos_hdr *pwlanhdr;
3485 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3486 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3487 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3489 DBG_8723A("%s\n", __func__);
3491 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3495 /* update attribute */
3496 pattrib = &pmgntframe->attrib;
3497 update_mgntframe_attrib23a(padapter, pattrib);
3499 pattrib->hdrlen += 2;
3500 pattrib->qos_en = true;
3502 pattrib->ack_policy = 0;
3505 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3507 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3508 pwlanhdr = (struct ieee80211_qos_hdr *)pframe;
3510 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3511 IEEE80211_STYPE_QOS_NULLFUNC);
3513 if ((pmlmeinfo->state&0x03) == MSR_AP)
3514 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3515 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3516 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3519 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
3521 pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK);
3522 pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) &
3523 IEEE80211_QOS_CTL_ACK_POLICY_MASK);
3525 pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
3527 ether_addr_copy(pwlanhdr->addr1, da);
3528 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3529 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3531 pwlanhdr->seq_ctrl =
3532 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3533 pmlmeext->mgnt_seq++;
3535 pframe += sizeof(struct ieee80211_qos_hdr);
3536 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3538 pattrib->last_txcmdsz = pattrib->pktlen;
3541 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3543 dump_mgntframe23a(padapter, pmgntframe);
3551 /* when wait_ms >0 , this function should be called at process context */
3552 /* da == NULL for station mode */
3553 int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3554 u16 tid, int try_cnt, int wait_ms)
3558 unsigned long start = jiffies;
3559 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3560 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3562 /* da == NULL, assume it's null data for sta to ap*/
3564 da = get_my_bssid23a(&pmlmeinfo->network);
3567 ret = _issue_qos_nulldata23a(padapter, da, tid,
3568 wait_ms > 0 ? true : false);
3572 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3575 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3577 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3584 if (try_cnt && wait_ms) {
3586 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3587 __func__, padapter->pnetdev->name,
3588 da, rtw_get_oper_ch23a(padapter),
3589 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3590 jiffies_to_msecs(jiffies - start));
3592 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3593 __func__, padapter->pnetdev->name,
3594 rtw_get_oper_ch23a(padapter),
3595 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3596 jiffies_to_msecs(jiffies - start));
3602 static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da,
3603 unsigned short reason, u8 wait_ack)
3605 struct xmit_frame *pmgntframe;
3606 struct pkt_attrib *pattrib;
3607 struct ieee80211_mgmt *mgmt;
3608 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3609 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3610 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3613 /* DBG_8723A("%s to %pM\n", __func__, da); */
3615 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3619 /* update attribute */
3620 pattrib = &pmgntframe->attrib;
3621 update_mgntframe_attrib23a(padapter, pattrib);
3622 pattrib->retry_ctrl = false;
3624 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3626 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3628 mgmt->frame_control =
3629 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
3631 ether_addr_copy(mgmt->da, da);
3632 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3633 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3635 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3636 pmlmeext->mgnt_seq++;
3638 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2;
3640 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
3642 pattrib->last_txcmdsz = pattrib->pktlen;
3645 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3647 dump_mgntframe23a(padapter, pmgntframe);
3655 int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
3656 unsigned short reason)
3658 DBG_8723A("%s to %pM\n", __func__, da);
3659 return _issue_deauth(padapter, da, reason, false);
3662 static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
3663 unsigned short reason, int try_cnt, int wait_ms)
3667 unsigned long start = jiffies;
3670 ret = _issue_deauth(padapter, da, reason,
3671 wait_ms >0 ? true : false);
3675 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3678 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3681 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3688 if (try_cnt && wait_ms) {
3690 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3691 __func__, padapter->pnetdev->name,
3692 da, rtw_get_oper_ch23a(padapter),
3693 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3694 jiffies_to_msecs(jiffies - start));
3696 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3697 __func__, padapter->pnetdev->name,
3698 rtw_get_oper_ch23a(padapter),
3699 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3700 jiffies_to_msecs(jiffies - start));
3706 void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
3707 u8 *ra, u8 new_ch, u8 ch_offset)
3709 struct xmit_frame *pmgntframe;
3710 struct pkt_attrib *pattrib;
3711 unsigned char *pframe;
3712 struct ieee80211_mgmt *mgmt;
3713 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3714 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3716 DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n",
3717 __func__, padapter->pnetdev->name, ra, new_ch, ch_offset);
3719 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3723 /* update attribute */
3724 pattrib = &pmgntframe->attrib;
3725 update_mgntframe_attrib23a(padapter, pattrib);
3727 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3729 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3731 mgmt->frame_control =
3732 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3734 ether_addr_copy(mgmt->da, ra); /* RA */
3735 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */
3736 ether_addr_copy(mgmt->bssid, ra); /* DA = RA */
3738 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3739 pmlmeext->mgnt_seq++;
3741 mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
3742 mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
3744 pframe = mgmt->u.action.u.chan_switch.variable;
3745 pattrib->pktlen = offsetof(struct ieee80211_mgmt,
3746 u.action.u.chan_switch.variable);
3748 pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
3750 pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
3751 hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
3753 pattrib->last_txcmdsz = pattrib->pktlen;
3755 dump_mgntframe23a(padapter, pmgntframe);
3758 void issue_action_BA23a(struct rtw_adapter *padapter,
3759 const unsigned char *raddr,
3760 unsigned char action, unsigned short status)
3764 u16 BA_starting_seqctrl;
3766 int max_rx_ampdu_factor;
3767 struct xmit_frame *pmgntframe;
3768 struct pkt_attrib *pattrib;
3769 struct ieee80211_mgmt *mgmt;
3770 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3771 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3772 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3773 struct sta_info *psta;
3774 struct sta_priv *pstapriv = &padapter->stapriv;
3775 struct registry_priv *pregpriv = &padapter->registrypriv;
3776 u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
3778 DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status);
3780 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3784 /* update attribute */
3785 pattrib = &pmgntframe->attrib;
3786 update_mgntframe_attrib23a(padapter, pattrib);
3788 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3790 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3792 mgmt->frame_control =
3793 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3795 ether_addr_copy(mgmt->da, raddr);
3796 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3797 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3799 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3800 pmlmeext->mgnt_seq++;
3802 mgmt->u.action.category = WLAN_CATEGORY_BACK;
3804 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1;
3806 status = cpu_to_le16(status);
3809 case WLAN_ACTION_ADDBA_REQ:
3810 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req);
3812 mgmt->u.action.u.addba_req.action_code = action;
3815 pmlmeinfo->dialogToken++;
3816 } while (pmlmeinfo->dialogToken == 0);
3818 mgmt->u.action.u.addba_req.dialog_token =
3819 pmlmeinfo->dialogToken;
3821 if (rtl8723a_BT_coexist(padapter) &&
3822 rtl8723a_BT_using_antenna_1(padapter) &&
3823 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3824 memcmp(raddr, tendaAPMac, 3))) {
3825 /* A-MSDU NOT Supported */
3827 /* immediate Block Ack */
3828 BA_para_set |= (1 << 1) &
3829 IEEE80211_ADDBA_PARAM_POLICY_MASK;
3831 BA_para_set |= (status << 2) &
3832 IEEE80211_ADDBA_PARAM_TID_MASK;
3833 /* max buffer size is 8 MSDU */
3834 BA_para_set |= (8 << 6) &
3835 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3837 /* immediate ack & 64 buffer size */
3838 BA_para_set = 0x1002 | ((status & 0xf) << 2);
3841 put_unaligned_le16(BA_para_set,
3842 &mgmt->u.action.u.addba_req.capab);
3845 put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout);
3847 psta = rtw_get_stainfo23a(pstapriv, raddr);
3851 idx = status & 0x07;
3853 (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1;
3855 DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
3858 psta->BA_starting_seqctrl[idx] = start_seq;
3860 BA_starting_seqctrl = start_seq << 4;
3862 BA_starting_seqctrl = 0;
3864 put_unaligned_le16(BA_starting_seqctrl,
3865 &mgmt->u.action.u.addba_req.start_seq_num);
3869 case WLAN_ACTION_ADDBA_RESP:
3870 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp);
3872 mgmt->u.action.u.addba_resp.action_code = action;
3873 mgmt->u.action.u.addba_resp.dialog_token =
3874 pmlmeinfo->ADDBA_req.dialog_token;
3875 put_unaligned_le16(status,
3876 &mgmt->u.action.u.addba_resp.status);
3878 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
3879 &max_rx_ampdu_factor);
3881 BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
3882 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
3883 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
3884 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
3885 BA_para_set = BA_para | 0x0800; /* 32 buffer size */
3886 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
3887 BA_para_set = BA_para | 0x0400; /* 16 buffer size */
3888 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
3889 BA_para_set = BA_para | 0x0200; /* 8 buffer size */
3891 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
3893 if (rtl8723a_BT_coexist(padapter) &&
3894 rtl8723a_BT_using_antenna_1(padapter) &&
3895 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3896 memcmp(raddr, tendaAPMac, 3))) {
3897 /* max buffer size is 8 MSDU */
3898 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3899 BA_para_set |= (8 << 6) &
3900 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3903 if (pregpriv->ampdu_amsdu == 0)/* disabled */
3904 BA_para_set &= ~BIT(0);
3905 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
3906 BA_para_set |= BIT(0);
3908 put_unaligned_le16(BA_para_set,
3909 &mgmt->u.action.u.addba_resp.capab);
3911 put_unaligned_le16(pmlmeinfo->ADDBA_req.BA_timeout_value,
3912 &mgmt->u.action.u.addba_resp.timeout);
3914 pattrib->pktlen += 8;
3916 case WLAN_ACTION_DELBA:
3917 pattrib->pktlen += sizeof(mgmt->u.action.u.delba);
3919 mgmt->u.action.u.delba.action_code = action;
3920 BA_para_set = (status & 0x1F) << 3;
3921 mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set);
3922 mgmt->u.action.u.delba.reason_code =
3923 cpu_to_le16(WLAN_REASON_QSTA_NOT_USE);
3925 pattrib->pktlen += 5;
3931 pattrib->last_txcmdsz = pattrib->pktlen;
3933 dump_mgntframe23a(padapter, pmgntframe);
3936 int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
3938 struct sta_priv *pstapriv = &padapter->stapriv;
3939 struct sta_info *psta = NULL;
3940 /* struct recv_reorder_ctrl *preorder_ctrl; */
3941 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3942 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3945 if ((pmlmeinfo->state&0x03) != MSR_AP)
3946 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3949 psta = rtw_get_stainfo23a(pstapriv, addr);
3953 if (initiator == 0) { /* recipient */
3954 for (tid = 0; tid < MAXTID; tid++) {
3955 if (psta->recvreorder_ctrl[tid].enable == true) {
3956 DBG_8723A("rx agg disable tid(%d)\n", tid);
3957 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3958 psta->recvreorder_ctrl[tid].enable = false;
3959 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
3962 } else if (initiator == 1) { /* originator */
3963 for (tid = 0; tid < MAXTID; tid++) {
3964 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
3965 DBG_8723A("tx agg disable tid(%d)\n", tid);
3966 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3967 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3968 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3976 int send_beacon23a(struct rtw_adapter *padapter)
3981 unsigned long start = jiffies;
3982 unsigned int passing_time;
3984 rtl8723a_bcn_valid(padapter);
3986 issue_beacon23a(padapter, 100);
3990 bxmitok = rtl8723a_get_bcn_valid(padapter);
3992 } while ((poll % 10) != 0 && !bxmitok &&
3993 !padapter->bSurpriseRemoved &&
3994 !padapter->bDriverStopped);
3996 } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
3997 !padapter->bDriverStopped);
3999 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4002 passing_time = jiffies_to_msecs(jiffies - start);
4005 DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
4009 if (passing_time > 100 || issue > 3)
4010 DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
4011 __func__, issue, poll, passing_time);
4016 /****************************************************************************
4018 Following are some utitity functions for WiFi MLME
4020 *****************************************************************************/
4022 bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
4026 u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
4027 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
4028 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
4029 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
4031 for (i = 0; i < sizeof(Channel_5G); i++)
4032 if (channel == Channel_5G[i])
4037 static void rtw_site_survey(struct rtw_adapter *padapter)
4039 unsigned char survey_channel = 0;
4040 enum rt_scan_type ScanType = SCAN_PASSIVE;
4041 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4042 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4043 struct rtw_ieee80211_channel *ch;
4045 if (pmlmeext->sitesurvey_res.channel_idx <
4046 pmlmeext->sitesurvey_res.ch_num) {
4047 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
4048 survey_channel = ch->hw_value;
4049 ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ?
4050 SCAN_PASSIVE : SCAN_ACTIVE;
4053 if (survey_channel != 0) {
4054 /* PAUSE 4-AC Queue when site_survey */
4055 if (pmlmeext->sitesurvey_res.channel_idx == 0)
4056 set_channel_bwmode23a(padapter, survey_channel,
4057 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
4058 HT_CHANNEL_WIDTH_20);
4060 SelectChannel23a(padapter, survey_channel);
4062 if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
4066 for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
4067 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
4068 /* todo: to issue two probe req??? */
4069 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4070 /* msleep(SURVEY_TO>>1); */
4071 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4075 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4076 /* todo: to issue two probe req??? */
4077 issue_probereq(padapter, NULL, NULL);
4078 /* msleep(SURVEY_TO>>1); */
4079 issue_probereq(padapter, NULL, NULL);
4083 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
4085 /* channel number is 0 or this channel is not valid. */
4086 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
4088 /* switch back to the original channel */
4090 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
4091 pmlmeext->cur_ch_offset,
4092 pmlmeext->cur_bwmode);
4094 /* flush 4-AC Queue after rtw_site_survey */
4098 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4100 /* restore RX GAIN */
4101 rtl8723a_set_initial_gain(padapter, 0xff);
4102 /* turn on dynamic functions */
4103 rtl8723a_odm_support_ability_restore(padapter);
4105 if (is_client_associated_to_ap23a(padapter) == true)
4106 issue_nulldata23a(padapter, NULL, 0, 3, 500);
4108 rtl8723a_mlme_sitesurvey(padapter, 0);
4110 report_surveydone_event23a(padapter);
4112 pmlmeext->chan_scan_time = SURVEY_TO;
4113 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
4119 /* collect bss info from Beacon and Probe request/response frames. */
4120 static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
4121 struct recv_frame *precv_frame)
4123 struct sk_buff *skb = precv_frame->pkt;
4124 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
4125 struct registry_priv *pregistrypriv = &padapter->registrypriv;
4126 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4127 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4128 struct wlan_bssid_ex *bssid;
4131 unsigned int length;
4136 bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
4140 if (ieee80211_is_beacon(mgmt->frame_control)) {
4141 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4142 pie = mgmt->u.beacon.variable;
4143 bssid->reserved = 1;
4145 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4146 bssid->beacon_interval =
4147 get_unaligned_le16(&mgmt->u.beacon.beacon_int);
4148 bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
4149 } else if (ieee80211_is_probe_req(mgmt->frame_control)) {
4150 length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
4151 pie = mgmt->u.probe_req.variable;
4152 bssid->reserved = 2;
4153 bssid->capability = 0;
4154 bssid->beacon_interval =
4155 padapter->registrypriv.dev_network.beacon_interval;
4157 } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
4159 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
4160 pie = mgmt->u.probe_resp.variable;
4161 bssid->reserved = 3;
4163 get_unaligned_le16(&mgmt->u.probe_resp.capab_info);
4164 bssid->beacon_interval =
4165 get_unaligned_le16(&mgmt->u.probe_resp.beacon_int);
4166 bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp);
4168 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4169 pie = mgmt->u.beacon.variable;
4170 bssid->reserved = 0;
4172 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4173 bssid->beacon_interval =
4174 padapter->registrypriv.dev_network.beacon_interval;
4178 if (length > MAX_IE_SZ) {
4179 /* DBG_8723A("IE too long for survey event\n"); */
4184 bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
4186 /* below is to copy the information element */
4187 bssid->IELength = length;
4188 memcpy(bssid->IEs, pie, bssid->IELength);
4190 /* get the signal strength */
4191 /* in dBM.raw data */
4192 bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
4193 bssid->SignalQuality =
4194 precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
4195 bssid->SignalStrength =
4196 precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
4199 p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength);
4202 DBG_8723A("marc: cannot find SSID for survey event\n");
4206 if (p[1] > IEEE80211_MAX_SSID_LEN) {
4207 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4208 "event\n", __func__, __LINE__, p[1]);
4211 memcpy(bssid->Ssid.ssid, p + 2, p[1]);
4212 bssid->Ssid.ssid_len = p[1];
4214 /* checking rate info... */
4216 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength);
4218 if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
4219 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4220 "event\n", __func__, __LINE__, p[1]);
4223 memcpy(bssid->SupportedRates, p + 2, p[1]);
4227 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs,
4230 if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
4231 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4232 "event\n", __func__, __LINE__, p[1]);
4235 memcpy(bssid->SupportedRates + i, p + 2, p[1]);
4238 /* Checking for DSConfig */
4239 p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength);
4241 bssid->DSConfig = 0;
4244 bssid->DSConfig = p[2];
4245 } else {/* In 5G, some ap do not have DSSET IE */
4246 /* checking HT info for channel */
4247 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs,
4250 struct ieee80211_ht_operation *HT_info =
4251 (struct ieee80211_ht_operation *)(p + 2);
4252 bssid->DSConfig = HT_info->primary_chan;
4253 } else /* use current channel */
4254 bssid->DSConfig = rtw_get_oper_ch23a(padapter);
4257 if (ieee80211_is_probe_req(mgmt->frame_control)) {
4259 bssid->ifmode = NL80211_IFTYPE_STATION;
4260 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4265 if (bssid->capability & WLAN_CAPABILITY_ESS) {
4266 bssid->ifmode = NL80211_IFTYPE_STATION;
4267 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4269 bssid->ifmode = NL80211_IFTYPE_ADHOC;
4270 ether_addr_copy(bssid->MacAddress, mgmt->bssid);
4273 if (bssid->capability & WLAN_CAPABILITY_PRIVACY)
4278 bssid->ATIMWindow = 0;
4280 /* 20/40 BSS Coexistence check */
4281 if (pregistrypriv->wifi_spec == 1 &&
4282 pmlmeinfo->bwmode_updated == false) {
4283 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4285 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs,
4287 if (p && p[1] > 0) {
4288 struct ieee80211_ht_cap *pHT_caps;
4290 pHT_caps = (struct ieee80211_ht_cap *)(p + 2);
4292 if (pHT_caps->cap_info &
4293 cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT))
4294 pmlmepriv->num_FortyMHzIntolerant++;
4296 pmlmepriv->num_sta_no_ht++;
4300 /* mark bss info receiving from nearby channel as SignalQuality 101 */
4301 if (bssid->DSConfig != rtw_get_oper_ch23a(padapter))
4302 bssid->SignalQuality = 101;
4310 static void start_create_ibss(struct rtw_adapter *padapter)
4312 unsigned short caps;
4313 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4314 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4315 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4317 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4318 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4320 /* update wireless mode */
4321 update_wireless_mode23a(padapter);
4323 /* update capability */
4324 caps = pnetwork->capability;
4325 update_capinfo23a(padapter, caps);
4326 if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */
4327 rtl8723a_set_sec_cfg(padapter, 0xcf);
4329 /* switch channel */
4330 /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4331 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
4333 rtl8723a_SetBeaconRelatedRegisters(padapter);
4335 /* set msr to MSR_ADHOC */
4336 pmlmeinfo->state = MSR_ADHOC;
4337 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4340 if (send_beacon23a(padapter) == _FAIL) {
4341 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
4342 "issuing beacon frame fail....\n");
4344 report_join_res23a(padapter, -1);
4345 pmlmeinfo->state = MSR_NOLINK;
4347 hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
4348 hw_var_set_mlme_join(padapter, 0);
4350 report_join_res23a(padapter, 1);
4351 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4354 DBG_8723A("%s: invalid cap:%x\n", __func__, caps);
4359 static void start_clnt_join(struct rtw_adapter *padapter)
4361 unsigned short caps;
4363 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4364 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4365 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4368 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4369 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4371 /* update wireless mode */
4372 update_wireless_mode23a(padapter);
4374 /* update capability */
4375 caps = pnetwork->capability;
4376 update_capinfo23a(padapter, caps);
4377 if (caps & WLAN_CAPABILITY_ESS) {
4378 /* switch channel */
4379 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4381 rtl8723a_set_media_status(padapter, MSR_INFRA);
4383 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
4386 rtl8723a_set_sec_cfg(padapter, val8);
4388 /* switch channel */
4389 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
4391 /* here wait for receiving the beacon to start auth */
4392 /* and enable a timer */
4393 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
4394 set_link_timer(pmlmeext, beacon_timeout);
4395 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
4396 msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
4397 pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA;
4398 } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */
4399 rtl8723a_set_media_status(padapter, MSR_ADHOC);
4401 rtl8723a_set_sec_cfg(padapter, 0xcf);
4403 /* switch channel */
4404 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4406 rtl8723a_SetBeaconRelatedRegisters(padapter);
4408 pmlmeinfo->state = MSR_ADHOC;
4410 report_join_res23a(padapter, 1);
4412 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
4417 static void start_clnt_auth(struct rtw_adapter *padapter)
4419 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4420 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4422 del_timer_sync(&pmlmeext->link_timer);
4424 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4425 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4427 pmlmeinfo->auth_seq = 1;
4428 pmlmeinfo->reauth_count = 0;
4429 pmlmeinfo->reassoc_count = 0;
4430 pmlmeinfo->link_count = 0;
4431 pmlmeext->retry = 0;
4433 /* Because of AP's not receiving deauth before */
4434 /* AP may: 1)not response auth or 2)deauth us after link is complete */
4435 /* issue deauth before issuing auth to deal with the situation */
4436 /* Commented by Albert 2012/07/21 */
4437 /* For the Win8 P2P connection, it will be hard to have a
4438 successful connection if this Wi-Fi doesn't connect to it. */
4439 issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress,
4440 WLAN_REASON_DEAUTH_LEAVING);
4442 DBG_8723A_LEVEL(_drv_always_, "start auth\n");
4443 issue_auth(padapter, NULL, 0);
4445 set_link_timer(pmlmeext, REAUTH_TO);
4448 static void start_clnt_assoc(struct rtw_adapter *padapter)
4450 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4451 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4453 del_timer_sync(&pmlmeext->link_timer);
4455 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4456 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4458 issue_assocreq(padapter);
4460 set_link_timer(pmlmeext, REASSOC_TO);
4463 int receive_disconnect23a(struct rtw_adapter *padapter,
4464 unsigned char *MacAddr, unsigned short reason)
4466 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4467 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4470 if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
4473 DBG_8723A("%s\n", __func__);
4475 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
4476 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4477 pmlmeinfo->state = MSR_NOLINK;
4478 report_del_sta_event23a(padapter, MacAddr, reason);
4480 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4481 pmlmeinfo->state = MSR_NOLINK;
4482 report_join_res23a(padapter, -2);
4489 static void process_80211d(struct rtw_adapter *padapter,
4490 struct wlan_bssid_ex *bssid)
4492 struct registry_priv *pregistrypriv;
4493 struct mlme_ext_priv *pmlmeext;
4494 struct rt_channel_info *chplan_new;
4498 pregistrypriv = &padapter->registrypriv;
4499 pmlmeext = &padapter->mlmeextpriv;
4501 /* Adjust channel plan by AP Country IE */
4502 if (pregistrypriv->enable80211d &&
4503 !pmlmeext->update_channel_plan_by_ap_done) {
4505 struct rt_channel_plan chplan_ap;
4506 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4508 u8 fcn; /* first channel number */
4509 u8 noc; /* number of channel */
4512 ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs,
4514 if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
4521 memcpy(country, p, 3);
4525 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4526 "%s: 802.11d country =%s\n", __func__, country);
4529 while ((ie - p) >= 3) {
4534 for (j = 0; j < noc; j++) {
4536 channel = fcn + j; /* 2.4 GHz */
4538 channel = fcn + j * 4; /* 5 GHz */
4540 chplan_ap.Channel[i++] = channel;
4545 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4546 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4547 chplan_new = pmlmeext->channel_set;
4550 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4552 if (i == MAX_CHANNEL_NUM ||
4553 chplan_sta[i].ChannelNum == 0 ||
4554 chplan_sta[i].ChannelNum > 14)
4557 if (j == chplan_ap.Len ||
4558 chplan_ap.Channel[j] > 14)
4561 if (chplan_sta[i].ChannelNum ==
4562 chplan_ap.Channel[j]) {
4563 chplan_new[k].ChannelNum =
4564 chplan_ap.Channel[j];
4565 chplan_new[k].ScanType = SCAN_ACTIVE;
4569 } else if (chplan_sta[i].ChannelNum <
4570 chplan_ap.Channel[j]) {
4571 chplan_new[k].ChannelNum =
4572 chplan_sta[i].ChannelNum;
4573 chplan_new[k].ScanType =
4577 } else if (chplan_sta[i].ChannelNum >
4578 chplan_ap.Channel[j]) {
4579 chplan_new[k].ChannelNum =
4580 chplan_ap.Channel[j];
4581 chplan_new[k].ScanType =
4588 /* change AP not support channel to Passive scan */
4589 while (i < MAX_CHANNEL_NUM &&
4590 chplan_sta[i].ChannelNum != 0 &&
4591 chplan_sta[i].ChannelNum <= 14) {
4592 chplan_new[k].ChannelNum =
4593 chplan_sta[i].ChannelNum;
4594 chplan_new[k].ScanType = SCAN_PASSIVE;
4599 /* add channel AP supported */
4600 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
4601 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4602 chplan_new[k].ScanType = SCAN_ACTIVE;
4607 /* keep original STA 2.4G channel plan */
4608 while (i < MAX_CHANNEL_NUM &&
4609 chplan_sta[i].ChannelNum != 0 &&
4610 chplan_sta[i].ChannelNum <= 14) {
4611 chplan_new[k].ChannelNum =
4612 chplan_sta[i].ChannelNum;
4613 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4618 /* skip AP 2.4G channel plan */
4619 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
4623 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4625 if (i == MAX_CHANNEL_NUM ||
4626 chplan_sta[i].ChannelNum == 0)
4629 if (j == chplan_ap.Len ||
4630 chplan_ap.Channel[j] == 0)
4633 if (chplan_sta[i].ChannelNum ==
4634 chplan_ap.Channel[j]) {
4635 chplan_new[k].ChannelNum =
4636 chplan_ap.Channel[j];
4637 chplan_new[k].ScanType = SCAN_ACTIVE;
4641 } else if (chplan_sta[i].ChannelNum <
4642 chplan_ap.Channel[j]) {
4643 chplan_new[k].ChannelNum =
4644 chplan_sta[i].ChannelNum;
4645 chplan_new[k].ScanType = SCAN_PASSIVE;
4648 } else if (chplan_sta[i].ChannelNum >
4649 chplan_ap.Channel[j]) {
4650 chplan_new[k].ChannelNum =
4651 chplan_ap.Channel[j];
4652 chplan_new[k].ScanType = SCAN_ACTIVE;
4658 /* change AP not support channel to Passive scan */
4659 while (i < MAX_CHANNEL_NUM &&
4660 chplan_sta[i].ChannelNum != 0) {
4661 chplan_new[k].ChannelNum =
4662 chplan_sta[i].ChannelNum;
4663 chplan_new[k].ScanType = SCAN_PASSIVE;
4668 /* add channel AP supported */
4669 while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
4670 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4671 chplan_new[k].ScanType = SCAN_ACTIVE;
4676 /* keep original STA 5G channel plan */
4677 while (i < MAX_CHANNEL_NUM &&
4678 chplan_sta[i].ChannelNum != 0) {
4679 chplan_new[k].ChannelNum =
4680 chplan_sta[i].ChannelNum;
4681 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4686 pmlmeext->update_channel_plan_by_ap_done = 1;
4689 /* If channel is used by AP, set channel scan type to active */
4690 channel = bssid->DSConfig;
4691 chplan_new = pmlmeext->channel_set;
4693 while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
4694 if (chplan_new[i].ChannelNum == channel) {
4695 if (chplan_new[i].ScanType == SCAN_PASSIVE) {
4696 /* 5G Bnad 2, 3 (DFS) doesn't change
4698 if (channel >= 52 && channel <= 144)
4701 chplan_new[i].ScanType = SCAN_ACTIVE;
4702 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4703 "%s: change channel %d scan type from passive to active\n",
4712 /****************************************************************************
4714 Following are the functions to report events
4716 *****************************************************************************/
4718 void report_survey_event23a(struct rtw_adapter *padapter,
4719 struct recv_frame *precv_frame)
4721 struct cmd_obj *pcmd_obj;
4724 struct survey_event *psurvey_evt;
4725 struct C2HEvent_Header *pc2h_evt_hdr;
4726 struct mlme_ext_priv *pmlmeext;
4727 struct cmd_priv *pcmdpriv;
4732 pmlmeext = &padapter->mlmeextpriv;
4733 pcmdpriv = &padapter->cmdpriv;
4735 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4739 cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
4740 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4746 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4747 pcmd_obj->cmdsz = cmdsz;
4748 pcmd_obj->parmbuf = pevtcmd;
4750 pcmd_obj->rsp = NULL;
4751 pcmd_obj->rspsz = 0;
4753 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4754 pc2h_evt_hdr->len = sizeof(struct survey_event);
4755 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4756 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4758 psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4760 psurvey_evt->bss = collect_bss_info(padapter, precv_frame);
4761 if (!psurvey_evt->bss) {
4767 process_80211d(padapter, psurvey_evt->bss);
4769 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4771 pmlmeext->sitesurvey_res.bss_cnt++;
4776 void report_surveydone_event23a(struct rtw_adapter *padapter)
4778 struct cmd_obj *pcmd_obj;
4781 struct surveydone_event *psurveydone_evt;
4782 struct C2HEvent_Header *pc2h_evt_hdr;
4783 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4784 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4786 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4790 cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
4791 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4797 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4798 pcmd_obj->cmdsz = cmdsz;
4799 pcmd_obj->parmbuf = pevtcmd;
4801 pcmd_obj->rsp = NULL;
4802 pcmd_obj->rspsz = 0;
4804 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4805 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4806 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4807 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4809 psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4810 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4812 DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
4814 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4819 void report_join_res23a(struct rtw_adapter *padapter, int res)
4821 struct cmd_obj *pcmd_obj;
4824 struct joinbss_event *pjoinbss_evt;
4825 struct C2HEvent_Header *pc2h_evt_hdr;
4826 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4827 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4828 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4830 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4834 cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
4835 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4841 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4842 pcmd_obj->cmdsz = cmdsz;
4843 pcmd_obj->parmbuf = pevtcmd;
4845 pcmd_obj->rsp = NULL;
4846 pcmd_obj->rspsz = 0;
4848 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4849 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4850 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4851 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4853 pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4854 memcpy((unsigned char *)&pjoinbss_evt->network.network,
4855 &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
4856 pjoinbss_evt->network.join_res = res;
4858 DBG_8723A("report_join_res23a(%d)\n", res);
4860 rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
4862 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4867 void report_del_sta_event23a(struct rtw_adapter *padapter,
4868 unsigned char *MacAddr, unsigned short reason)
4870 struct cmd_obj *pcmd_obj;
4873 struct sta_info *psta;
4875 struct stadel_event *pdel_sta_evt;
4876 struct C2HEvent_Header *pc2h_evt_hdr;
4877 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4878 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4880 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4884 cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
4885 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4891 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4892 pcmd_obj->cmdsz = cmdsz;
4893 pcmd_obj->parmbuf = pevtcmd;
4895 pcmd_obj->rsp = NULL;
4896 pcmd_obj->rspsz = 0;
4898 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4899 pc2h_evt_hdr->len = sizeof(struct stadel_event);
4900 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4901 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4903 pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4904 ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
4905 memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
4908 psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
4910 mac_id = (int)psta->mac_id;
4914 pdel_sta_evt->mac_id = mac_id;
4916 DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
4918 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4923 void report_add_sta_event23a(struct rtw_adapter *padapter,
4924 unsigned char *MacAddr, int cam_idx)
4926 struct cmd_obj *pcmd_obj;
4929 struct stassoc_event *padd_sta_evt;
4930 struct C2HEvent_Header *pc2h_evt_hdr;
4931 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4932 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4934 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4938 cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
4939 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4945 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4946 pcmd_obj->cmdsz = cmdsz;
4947 pcmd_obj->parmbuf = pevtcmd;
4949 pcmd_obj->rsp = NULL;
4950 pcmd_obj->rspsz = 0;
4952 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4953 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4954 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4955 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4957 padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4958 ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
4959 padd_sta_evt->cam_id = cam_idx;
4961 DBG_8723A("report_add_sta_event23a: add STA\n");
4963 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4968 /****************************************************************************
4970 Following are the event callback functions
4972 *****************************************************************************/
4974 /* for sta/adhoc mode */
4975 void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
4977 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4978 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4979 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4982 VCS_update23a(padapter, psta);
4985 if (pmlmepriv->htpriv.ht_option) {
4986 psta->htpriv.ht_option = true;
4988 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4990 if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
4991 psta->htpriv.sgi = true;
4993 psta->qos_option = true;
4996 psta->htpriv.ht_option = false;
4998 psta->htpriv.ampdu_enable = false;
5000 psta->htpriv.sgi = false;
5001 psta->qos_option = false;
5004 psta->htpriv.bwmode = pmlmeext->cur_bwmode;
5005 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
5007 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
5008 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
5011 if (pmlmepriv->qos_option)
5012 psta->qos_option = true;
5014 psta->state = _FW_LINKED;
5017 void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter,
5020 struct sta_info *psta, *psta_bmc;
5021 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5022 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5023 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5024 struct sta_priv *pstapriv = &padapter->stapriv;
5027 hw_var_set_mlme_join(padapter, 1);
5028 hw_var_set_bssid(padapter, null_addr);
5030 /* restore to initial setting. */
5031 update_tx_basic_rate23a(padapter,
5032 padapter->registrypriv.wireless_mode);
5034 goto exit_mlmeext_joinbss_event_callback23a;
5037 if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
5039 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
5041 pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
5042 update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
5043 Update_RA_Entry23a(padapter, psta_bmc);
5047 /* turn on dynamic functions */
5048 rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
5050 /* update IOT-releated issue */
5051 update_IOT_info23a(padapter);
5053 HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
5056 rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
5058 /* update capability */
5059 update_capinfo23a(padapter, pmlmeinfo->capability);
5061 /* WMM, Update EDCA param */
5062 WMMOnAssocRsp23a(padapter);
5065 HTOnAssocRsp23a(padapter);
5067 /* Set cur_channel&cur_bwmode&cur_ch_offset */
5068 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5070 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
5071 if (psta) { /* only for infra. mode */
5072 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5074 /* DBG_8723A("set_sta_rate23a\n"); */
5076 psta->wireless_mode = pmlmeext->cur_wireless_mode;
5078 /* set per sta rate after updating HT cap. */
5079 set_sta_rate23a(padapter, psta);
5082 hw_var_set_mlme_join(padapter, 2);
5084 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
5085 /* correcting TSF */
5086 rtw_correct_TSF(padapter);
5088 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5091 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
5093 exit_mlmeext_joinbss_event_callback23a:
5094 DBG_8723A("=>%s\n", __func__);
5097 void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter,
5098 struct sta_info *psta)
5100 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5101 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5103 DBG_8723A("%s\n", __func__);
5105 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
5106 /* adhoc master or sta_count>1 */
5107 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5109 } else { /* adhoc client */
5110 /* correcting TSF */
5111 rtw_correct_TSF(padapter);
5114 if (send_beacon23a(padapter) != _SUCCESS) {
5115 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5117 pmlmeinfo->state ^= MSR_ADHOC;
5122 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
5124 hw_var_set_mlme_join(padapter, 2);
5127 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5129 /* rate radaptive */
5130 Update_RA_Entry23a(padapter, psta);
5132 /* update adhoc sta_info */
5133 update_sta_info23a(padapter, psta);
5136 void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
5138 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5139 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5141 if (is_client_associated_to_ap23a(padapter) ||
5142 is_IBSS_empty23a(padapter)) {
5143 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5145 hw_var_set_mlme_disconnect(padapter);
5146 hw_var_set_bssid(padapter, null_addr);
5148 /* restore to initial setting. */
5149 update_tx_basic_rate23a(padapter,
5150 padapter->registrypriv.wireless_mode);
5152 /* switch to the 20M Hz mode after disconnect */
5153 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5154 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5156 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5157 pmlmeext->cur_ch_offset,
5158 pmlmeext->cur_bwmode);
5160 flush_all_cam_entry23a(padapter);
5162 pmlmeinfo->state = MSR_NOLINK;
5164 /* set MSR to no link state -> infra. mode */
5165 rtl8723a_set_media_status(padapter, MSR_INFRA);
5167 del_timer_sync(&pmlmeext->link_timer);
5171 static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
5175 if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) &&
5176 sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
5177 sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
5182 sta_update_last_rx_pkts(psta);
5186 void linked_status_chk23a(struct rtw_adapter *padapter)
5189 struct sta_info *psta;
5190 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5191 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5192 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5193 struct sta_priv *pstapriv = &padapter->stapriv;
5195 if (is_client_associated_to_ap23a(padapter)) {
5196 /* linked infrastructure client mode */
5198 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5203 psta = rtw_get_stainfo23a(pstapriv,
5204 pmlmeinfo->network.MacAddress);
5206 bool is_p2p_enable = false;
5208 if (chk_ap_is_alive(padapter, psta) == false)
5211 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5214 if (pmlmeext->active_keep_alive_check &&
5215 (rx_chk == _FAIL || tx_chk == _FAIL)) {
5216 u8 backup_oper_channel = 0;
5218 /* switch to correct channel of current
5219 network before issue keep-alive frames */
5220 if (rtw_get_oper_ch23a(padapter) !=
5221 pmlmeext->cur_channel) {
5222 backup_oper_channel =
5223 rtw_get_oper_ch23a(padapter);
5224 SelectChannel23a(padapter,
5225 pmlmeext->cur_channel);
5228 if (rx_chk != _SUCCESS)
5229 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
5231 if ((tx_chk != _SUCCESS &&
5232 pmlmeinfo->link_count++ == 0xf) ||
5233 rx_chk != _SUCCESS) {
5234 tx_chk = issue_nulldata23a(padapter,
5237 /* if tx acked and p2p disabled,
5238 set rx_chk _SUCCESS to reset retry
5240 if (tx_chk == _SUCCESS &&
5245 /* back to the original operation channel */
5246 if (backup_oper_channel>0)
5247 SelectChannel23a(padapter,
5248 backup_oper_channel);
5250 if (rx_chk != _SUCCESS) {
5251 if (pmlmeext->retry == 0) {
5252 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5253 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5254 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5258 if (tx_chk != _SUCCESS &&
5259 pmlmeinfo->link_count++ == 0xf)
5260 tx_chk = issue_nulldata23a(padapter,
5265 if (rx_chk == _FAIL) {
5267 if (pmlmeext->retry > rx_chk_limit) {
5268 DBG_8723A_LEVEL(_drv_always_,
5269 "%s(%s): disconnect or "
5270 "roaming\n", __func__,
5271 padapter->pnetdev->name);
5272 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
5273 WLAN_REASON_EXPIRATION_CHK);
5277 pmlmeext->retry = 0;
5279 if (tx_chk == _FAIL)
5280 pmlmeinfo->link_count &= 0xf;
5282 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5283 pmlmeinfo->link_count = 0;
5287 } else if (is_client_associated_to_ibss23a(padapter)) {
5288 /* linked IBSS mode */
5289 /* for each assoc list entry to check the rx pkt counter */
5290 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5291 if (pmlmeinfo->FW_sta_info[i].status == 1) {
5292 psta = pmlmeinfo->FW_sta_info[i].psta;
5297 if (pmlmeinfo->FW_sta_info[i].rx_pkt ==
5298 sta_rx_pkts(psta)) {
5300 if (pmlmeinfo->FW_sta_info[i].retry<3) {
5301 pmlmeinfo->FW_sta_info[i].retry++;
5303 pmlmeinfo->FW_sta_info[i].retry = 0;
5304 pmlmeinfo->FW_sta_info[i].status = 0;
5305 report_del_sta_event23a(padapter, psta->hwaddr,
5306 65535/* indicate disconnect caused by no rx */
5310 pmlmeinfo->FW_sta_info[i].retry = 0;
5311 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5315 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5319 static void survey_timer_hdl(unsigned long data)
5321 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5322 struct cmd_obj *ph2c;
5323 struct sitesurvey_parm *psurveyPara;
5324 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5325 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5327 /* issue rtw_sitesurvey_cmd23a */
5328 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5329 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
5330 pmlmeext->sitesurvey_res.channel_idx++;
5332 if (pmlmeext->scan_abort == true) {
5333 pmlmeext->sitesurvey_res.channel_idx =
5334 pmlmeext->sitesurvey_res.ch_num;
5335 DBG_8723A("%s idx:%d\n", __func__,
5336 pmlmeext->sitesurvey_res.channel_idx);
5338 pmlmeext->scan_abort = false;/* reset */
5341 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
5343 goto exit_survey_timer_hdl;
5345 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm),
5349 goto exit_survey_timer_hdl;
5352 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
5353 GEN_CMD_CODE(_SiteSurvey));
5354 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
5357 exit_survey_timer_hdl:
5361 static void link_timer_hdl(unsigned long data)
5363 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5364 /* static unsigned int rx_pkt = 0; */
5365 /* static u64 tx_cnt = 0; */
5366 /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
5367 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5368 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5369 /* struct sta_priv *pstapriv = &padapter->stapriv; */
5371 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5372 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
5373 pmlmeinfo->state = MSR_NOLINK;
5374 report_join_res23a(padapter, -3);
5375 } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5377 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5378 /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5380 pmlmeinfo->state = 0;
5381 report_join_res23a(padapter, -1);
5386 /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5387 /* pmlmeinfo->reauth_count = 0; */
5391 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
5392 pmlmeinfo->auth_seq = 1;
5393 issue_auth(padapter, NULL, 0);
5394 set_link_timer(pmlmeext, REAUTH_TO);
5395 } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5396 /* re-assoc timer */
5397 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5398 pmlmeinfo->state = MSR_NOLINK;
5399 report_join_res23a(padapter, -2);
5403 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
5404 issue_assocreq(padapter);
5405 set_link_timer(pmlmeext, REASSOC_TO);
5411 static void addba_timer_hdl(unsigned long data)
5413 struct sta_info *psta = (struct sta_info *)data;
5414 struct ht_priv *phtpriv;
5419 phtpriv = &psta->htpriv;
5421 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5422 if (phtpriv->candidate_tid_bitmap)
5423 phtpriv->candidate_tid_bitmap = 0x0;
5427 void init_addba_retry_timer23a(struct sta_info *psta)
5429 setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
5430 (unsigned long)psta);
5433 void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
5435 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5437 setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
5438 (unsigned long)padapter);
5440 setup_timer(&pmlmeext->link_timer, link_timer_hdl,
5441 (unsigned long)padapter);
5444 int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5449 int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5451 enum nl80211_iftype type;
5452 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5453 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5454 const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5456 switch (psetop->mode) {
5457 case NL80211_IFTYPE_P2P_GO:
5458 case NL80211_IFTYPE_AP:
5459 pmlmeinfo->state = MSR_AP;
5462 case NL80211_IFTYPE_P2P_CLIENT:
5463 case NL80211_IFTYPE_STATION:
5465 pmlmeinfo->state &= ~(BIT(0)|BIT(1));
5466 /* set to STATION_STATE */
5467 pmlmeinfo->state |= MSR_INFRA;
5470 case NL80211_IFTYPE_ADHOC:
5478 hw_var_set_opmode(padapter, type);
5479 /* Set_NETYPE0_MSR(padapter, type); */
5484 int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5486 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5487 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5488 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5489 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5490 /* u32 initialgain; */
5492 if (pparm->ifmode == NL80211_IFTYPE_AP ||
5493 pparm->ifmode == NL80211_IFTYPE_P2P_GO) {
5494 #ifdef CONFIG_8723AU_AP_MODE
5495 if (pmlmeinfo->state == MSR_AP) {
5502 /* below is for ad-hoc master */
5503 if (pparm->ifmode == NL80211_IFTYPE_ADHOC) {
5504 rtw_joinbss_reset23a(padapter);
5506 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5507 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5508 pmlmeinfo->ERP_enable = 0;
5509 pmlmeinfo->WMM_enable = 0;
5510 pmlmeinfo->HT_enable = 0;
5511 pmlmeinfo->HT_caps_enable = 0;
5512 pmlmeinfo->HT_info_enable = 0;
5514 /* disable dynamic functions, such as high power, DIG */
5515 rtl8723a_odm_support_ability_backup(padapter);
5517 rtl8723a_odm_support_ability_clr(padapter,
5518 DYNAMIC_FUNC_DISABLE);
5520 /* cancel link timer */
5521 del_timer_sync(&pmlmeext->link_timer);
5524 flush_all_cam_entry23a(padapter);
5526 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5527 return H2C_PARAMETERS_ERROR;
5529 memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
5531 start_create_ibss(padapter);
5537 int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5539 struct registry_priv *pregpriv = &padapter->registrypriv;
5540 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5541 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5542 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5543 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5544 struct ieee80211_ht_operation *pht_info;
5547 /* u32 initialgain; */
5550 /* check already connecting to AP or not */
5551 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5552 if (pmlmeinfo->state & MSR_INFRA)
5553 issue_deauth_ex(padapter, pnetwork->MacAddress,
5554 WLAN_REASON_DEAUTH_LEAVING, 5, 100);
5556 pmlmeinfo->state = MSR_NOLINK;
5559 flush_all_cam_entry23a(padapter);
5561 del_timer_sync(&pmlmeext->link_timer);
5563 /* set MSR to nolink -> infra. mode */
5564 rtl8723a_set_media_status(padapter, MSR_INFRA);
5566 hw_var_set_mlme_disconnect(padapter);
5569 rtw_joinbss_reset23a(padapter);
5571 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5572 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5573 pmlmeinfo->ERP_enable = 0;
5574 pmlmeinfo->WMM_enable = 0;
5575 pmlmeinfo->HT_enable = 0;
5576 pmlmeinfo->HT_caps_enable = 0;
5577 pmlmeinfo->HT_info_enable = 0;
5578 pmlmeinfo->bwmode_updated = false;
5579 /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
5581 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5582 return H2C_PARAMETERS_ERROR;
5584 memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
5586 /* Check AP vendor to move rtw_joinbss_cmd23a() */
5587 /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
5588 pnetwork->IELength); */
5590 for (i = 0; i < pnetwork->IELength;) {
5591 p = pnetwork->IEs + i;
5594 case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
5595 if (!memcmp(p + 2, WMM_OUI23A, 4))
5596 pmlmeinfo->WMM_enable = 1;
5599 case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */
5600 pmlmeinfo->HT_caps_enable = 1;
5603 case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */
5604 pmlmeinfo->HT_info_enable = 1;
5606 /* spec case only for cisco's ap because cisco's ap
5607 * issue assoc rsp using mcs rate @40MHz or @20MHz */
5608 pht_info = (struct ieee80211_ht_operation *)(p + 2);
5610 if (pregpriv->cbw40_enable &&
5611 (pht_info->ht_param &
5612 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
5613 /* switch to the 40M Hz mode according to AP */
5614 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
5615 switch (pht_info->ht_param &
5616 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
5617 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
5618 pmlmeext->cur_ch_offset =
5619 HAL_PRIME_CHNL_OFFSET_LOWER;
5622 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
5623 pmlmeext->cur_ch_offset =
5624 HAL_PRIME_CHNL_OFFSET_UPPER;
5628 pmlmeext->cur_ch_offset =
5629 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5633 DBG_8723A("set ch/bw before connected\n");
5644 hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
5645 hw_var_set_mlme_join(padapter, 0);
5647 /* cancel link timer */
5648 del_timer_sync(&pmlmeext->link_timer);
5650 start_clnt_join(padapter);
5655 int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5657 const struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5658 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5659 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5660 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5662 if (is_client_associated_to_ap23a(padapter)) {
5663 issue_deauth_ex(padapter, pnetwork->MacAddress,
5664 WLAN_REASON_DEAUTH_LEAVING,
5665 param->deauth_timeout_ms/100, 100);
5668 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5670 /* pmlmeinfo->state = MSR_NOLINK; */
5672 hw_var_set_mlme_disconnect(padapter);
5673 hw_var_set_bssid(padapter, null_addr);
5675 /* restore to initial setting. */
5676 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
5678 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC ||
5679 (pmlmeinfo->state & 0x03) == MSR_AP)
5680 rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */
5682 /* set MSR to no link state -> infra. mode */
5683 rtl8723a_set_media_status(padapter, MSR_INFRA);
5685 pmlmeinfo->state = MSR_NOLINK;
5687 /* switch to the 20M Hz mode after disconnect */
5688 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5689 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5691 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5692 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5694 flush_all_cam_entry23a(padapter);
5696 del_timer_sync(&pmlmeext->link_timer);
5698 rtw_free_uc_swdec_pending_queue23a(padapter);
5704 rtw_scan_ch_decision(struct rtw_adapter *padapter,
5705 struct rtw_ieee80211_channel *out, u32 out_num,
5706 const struct rtw_ieee80211_channel *in, u32 in_num)
5709 int scan_ch_num = 0;
5711 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5713 /* clear out first */
5714 memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5716 /* acquire channels from in */
5718 for (i = 0;i<in_num;i++) {
5719 if (in[i].hw_value &&
5720 !(in[i].flags & IEEE80211_CHAN_DISABLED) &&
5721 (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set,
5722 in[i].hw_value)) >= 0) {
5723 memcpy(&out[j], &in[i],
5724 sizeof(struct rtw_ieee80211_channel));
5726 if (pmlmeext->channel_set[set_idx].ScanType ==
5728 out[j].flags &= IEEE80211_CHAN_NO_IR;
5736 /* if out is empty, use channel_set as default */
5738 for (i = 0;i<pmlmeext->max_chan_nums;i++) {
5739 out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
5741 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5742 out[i].flags &= IEEE80211_CHAN_NO_IR;
5748 if (padapter->setband == GHZ_24) { /* 2.4G */
5749 for (i = 0; i < j ; i++) {
5750 if (out[i].hw_value > 35)
5752 sizeof(struct rtw_ieee80211_channel));
5757 } else if (padapter->setband == GHZ_50) { /* 5G */
5758 for (i = 0; i < j ; i++) {
5759 if (out[i].hw_value > 35) {
5760 memcpy(&out[scan_ch_num++], &out[i],
5761 sizeof(struct rtw_ieee80211_channel));
5771 int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5773 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5774 const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
5775 u8 bdelayscan = false;
5779 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5780 pmlmeext->sitesurvey_res.state = SCAN_START;
5781 pmlmeext->sitesurvey_res.bss_cnt = 0;
5782 pmlmeext->sitesurvey_res.channel_idx = 0;
5784 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5785 if (pparm->ssid[i].ssid_len) {
5786 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
5787 pparm->ssid[i].ssid,
5788 IEEE80211_MAX_SSID_LEN);
5789 pmlmeext->sitesurvey_res.ssid[i].ssid_len =
5790 pparm->ssid[i].ssid_len;
5792 pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
5796 pmlmeext->sitesurvey_res.ch_num =
5797 rtw_scan_ch_decision(padapter,
5798 pmlmeext->sitesurvey_res.ch,
5799 RTW_CHANNEL_SCAN_AMOUNT,
5800 pparm->ch, pparm->ch_num);
5802 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5804 /* issue null data if associating to the AP */
5805 if (is_client_associated_to_ap23a(padapter)) {
5806 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5808 /* switch to correct channel of current network
5809 before issue keep-alive frames */
5810 if (rtw_get_oper_ch23a(padapter) !=
5811 pmlmeext->cur_channel)
5812 SelectChannel23a(padapter,
5813 pmlmeext->cur_channel);
5815 issue_nulldata23a(padapter, NULL, 1, 3, 500);
5821 /* delay 50ms to protect nulldata(1). */
5822 set_survey_timer(pmlmeext, 50);
5827 if (pmlmeext->sitesurvey_res.state == SCAN_START ||
5828 pmlmeext->sitesurvey_res.state == SCAN_TXNULL) {
5829 /* disable dynamic functions, such as high power, DIG */
5830 rtl8723a_odm_support_ability_backup(padapter);
5831 rtl8723a_odm_support_ability_clr(padapter,
5832 DYNAMIC_FUNC_DISABLE);
5834 /* config the initial gain under scanning, need to
5835 write the BB registers */
5836 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
5841 rtl8723a_set_initial_gain(padapter, initialgain);
5843 /* set MSR to no link state */
5844 rtl8723a_set_media_status(padapter, MSR_NOLINK);
5846 rtl8723a_mlme_sitesurvey(padapter, 1);
5848 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5851 rtw_site_survey(padapter);
5856 int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5858 const struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
5859 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5860 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5862 if (pparm->mode < 4)
5863 pmlmeinfo->auth_algo = pparm->mode;
5868 int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5870 unsigned short ctrl;
5871 const struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
5872 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5873 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5874 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5876 /* main tx key for wep. */
5878 pmlmeinfo->key_index = pparm->keyid;
5881 ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid;
5883 DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 "
5884 "WEP104-5 TKIP-2 AES-4) keyid:%d\n",
5885 pparm->algorithm, pparm->keyid);
5886 rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
5888 /* allow multicast packets to driver */
5889 rtl8723a_on_rcr_am(padapter);
5894 int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5897 u8 cam_id;/* cam_entry */
5898 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5899 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5900 const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
5903 /* 0~3 for default key */
5905 /* for concurrent mode (ap+sta): */
5906 /* default key is disable, using sw encrypt/decrypt */
5907 /* cam_entry = 4 for sta mode (macid = 0) */
5908 /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
5910 /* for concurrent mode (sta+sta): */
5911 /* default key is disable, using sw encrypt/decrypt */
5912 /* cam_entry = 4 mapping to macid = 0 */
5913 /* cam_entry = 5 mapping to macid = 2 */
5917 DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 "
5918 "WEP104-5 TKIP-2 AES-4) camid:%d\n",
5919 pparm->algorithm, cam_id);
5920 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
5921 struct sta_info *psta;
5922 struct sta_priv *pstapriv = &padapter->stapriv;
5924 if (pparm->algorithm == 0) { /* clear cam entry */
5925 clear_cam_entry23a(padapter, pparm->id);
5926 return H2C_SUCCESS_RSP;
5929 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
5931 ctrl = BIT(15) | (pparm->algorithm << 2);
5933 DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm "
5934 "=%d\n", pparm->algorithm);
5936 if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) {
5937 DBG_8723A("r871x_set_stakey_hdl23a():set_stakey"
5938 " failed, mac_id(aid) =%d\n",
5940 return H2C_REJECTED;
5943 /* 0~3 for default key, cmd_id = macid + 3,
5945 cam_id = psta->mac_id + 3;
5947 DBG_8723A("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, "
5948 "cam_entry =%d\n", pparm->addr[0],
5949 pparm->addr[1], pparm->addr[2],
5950 pparm->addr[3], pparm->addr[4],
5951 pparm->addr[5], cam_id);
5953 rtl8723a_cam_write(padapter, cam_id, ctrl,
5954 pparm->addr, pparm->key);
5956 return H2C_SUCCESS_RSP;
5958 DBG_8723A("r871x_set_stakey_hdl23a(): sta has been "
5960 return H2C_REJECTED;
5964 /* below for sta mode */
5966 if (pparm->algorithm == 0) { /* clear cam entry */
5967 clear_cam_entry23a(padapter, pparm->id);
5971 ctrl = BIT(15) | (pparm->algorithm << 2);
5973 rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5975 pmlmeinfo->enc_algo = pparm->algorithm;
5980 int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5982 const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
5983 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5984 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5985 struct sta_info *psta;
5987 psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
5992 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
5993 pmlmeinfo->HT_enable) ||
5994 (pmlmeinfo->state & 0x03) == MSR_AP) {
5995 issue_action_BA23a(padapter, pparm->addr,
5996 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5997 mod_timer(&psta->addba_retry_timer,
5998 jiffies + msecs_to_jiffies(ADDBA_TO));
6000 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
6005 int set_tx_beacon_cmd23a(struct rtw_adapter *padapter)
6007 struct cmd_obj *ph2c;
6008 struct Tx_Beacon_param *ptxBeacon_parm;
6009 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
6010 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6011 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6015 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
6021 ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
6022 if (!ptxBeacon_parm) {
6028 memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
6029 sizeof(struct wlan_bssid_ex));
6031 len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs,
6032 ptxBeacon_parm->network.IELength,
6033 pmlmeinfo->hidden_ssid_mode);
6034 ptxBeacon_parm->network.IELength += len_diff;
6036 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm,
6037 GEN_CMD_CODE(_TX_Beacon));
6039 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
6045 int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6047 u8 evt_code, evt_seq;
6049 const struct C2HEvent_Header *c2h;
6050 void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf);
6052 c2h = (struct C2HEvent_Header *)pbuf;
6057 /* checking if event code is valid */
6058 if (evt_code >= MAX_C2HEVT) {
6059 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6060 "Event Code(%d) mismatch!\n", evt_code);
6064 /* checking if event size match the event parm size */
6065 if (wlanevents[evt_code].parmsize != 0 &&
6066 wlanevents[evt_code].parmsize != evt_sz) {
6067 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6068 "Event(%d) Parm Size mismatch (%d vs %d)!\n",
6069 evt_code, wlanevents[evt_code].parmsize, evt_sz);
6073 event_callback = wlanevents[evt_code].event_callback;
6074 event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header));
6081 int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6084 return H2C_PARAMETERS_ERROR;
6089 int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6091 if (send_beacon23a(padapter) == _FAIL) {
6092 DBG_8723A("issue_beacon23a, fail!\n");
6093 return H2C_PARAMETERS_ERROR;
6095 #ifdef CONFIG_8723AU_AP_MODE
6096 else { /* tx bc/mc frames after update TIM */
6097 struct sta_info *psta_bmc;
6098 struct list_head *plist, *phead, *ptmp;
6099 struct xmit_frame *pxmitframe;
6100 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6101 struct sta_priv *pstapriv = &padapter->stapriv;
6103 /* for BC/MC Frames */
6104 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
6108 if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) {
6109 msleep(10);/* 10ms, ATIM(HIQ) Windows */
6110 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
6111 spin_lock_bh(&pxmitpriv->lock);
6113 phead = get_list_head(&psta_bmc->sleep_q);
6115 list_for_each_safe(plist, ptmp, phead) {
6116 pxmitframe = container_of(plist,
6120 list_del_init(&pxmitframe->list);
6122 psta_bmc->sleepq_len--;
6123 if (psta_bmc->sleepq_len>0)
6124 pxmitframe->attrib.mdata = 1;
6126 pxmitframe->attrib.mdata = 0;
6128 pxmitframe->attrib.triggered = 1;
6130 pxmitframe->attrib.qsel = 0x11;/* HIQ */
6132 rtl8723au_hal_xmitframe_enqueue(padapter,
6136 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
6137 spin_unlock_bh(&pxmitpriv->lock);
6145 int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6147 const struct set_ch_parm *set_ch_parm;
6148 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6151 return H2C_PARAMETERS_ERROR;
6153 set_ch_parm = (struct set_ch_parm *)pbuf;
6155 DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__,
6156 padapter->pnetdev->name, set_ch_parm->ch,
6157 set_ch_parm->bw, set_ch_parm->ch_offset);
6159 pmlmeext->cur_channel = set_ch_parm->ch;
6160 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6161 pmlmeext->cur_bwmode = set_ch_parm->bw;
6163 set_channel_bwmode23a(padapter, set_ch_parm->ch,
6164 set_ch_parm->ch_offset, set_ch_parm->bw);
6169 int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6171 const struct SetChannelPlan_param *setChannelPlan_param;
6172 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6175 return H2C_PARAMETERS_ERROR;
6177 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6179 pmlmeext->max_chan_nums =
6180 init_channel_set(padapter, setChannelPlan_param->channel_plan,
6181 pmlmeext->channel_set);
6182 init_channel_list(padapter, pmlmeext->channel_set,
6183 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6188 int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6190 struct LedBlink_param *ledBlink_param;
6193 return H2C_PARAMETERS_ERROR;
6195 ledBlink_param = (struct LedBlink_param *)pbuf;
6200 int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6202 return H2C_REJECTED;
6205 /* TDLS_WRCR : write RCR DATA BIT */
6206 /* TDLS_SD_PTI : issue peer traffic indication */
6207 /* TDLS_CS_OFF : go back to the channel linked with AP,
6208 terminating channel switch procedure */
6209 /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and
6211 /* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */
6212 /* TDLS_OFF_CH : first time set channel to off channel */
6213 /* TDLS_BASE_CH : go back tp the channel linked with AP when set
6214 base channel as target channel */
6215 /* TDLS_P_OFF_CH : periodically go to off channel */
6216 /* TDLS_P_BASE_CH : periodically go back to base channel */
6217 /* TDLS_RS_RCR : restore RCR */
6218 /* TDLS_CKALV_PH1 : check alive timer phase1 */
6219 /* TDLS_CKALV_PH2 : check alive timer phase2 */
6220 /* TDLS_FREE_STA : free tdls sta */
6221 int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6223 return H2C_REJECTED;